Skip to content

oj-bundle コマンドと AtCoder Library の連携がうまくいっていない #345

Closed
@kmyk

Description

@kmyk

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)

選択肢一覧

  1. oj-bundle 側を修正する
    1. ユーザにオプションを指定してもらう
      1. --bundle-atcoder-library のようなオプションを作る (Feature/#342 #344)
      1. --force-bundle のようなオプションを作って、#include <...> でも常に展開してほしいファイルを指定できるようにする
    2. デフォルトの挙動を変更する
      1. #include "atcoder/..." の処理中で遭遇した #include <atcoder/...> は展開するようにする
      1. 一般に #include "foo/bar" の処理中で遭遇した #include <foo/baz> は展開するようにする
  2. AtCoder Library 側を修正する
    1. #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

@yosupo06 とりあえず oj-bundle 側の事情を抜きにして言える一般論「#include <...> は一般によくない」だけを書いた issue (atcoder/ac-library#71) を atcoder/ac-library に作りました。対応お願いします。なお、一般論だけを主張したのは、AtCoder Library 側では oj-bundle の都合をあまり気にするべきではないはずだからです

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions