distutils とかで command line option “-Wstrict-prototypes” is valid for Ada/C/ObjC but not for C++

Pythonには縁もゆかりもないC/C++をdistutilsでビルドするなんてことをやってると、よくお目にかかる@linux。

メッセージの通りで、C++ なのに -Wstrict-prototypes つけてると出る警告。「外せばいいじゃん」。その通り。

distutils は、原則として「Python にゆかりのあるものをビルドするため」に最適なもの。Python C 拡張は、API も C だし、C で書く方が主流なので、「C++ 愛してる」とちょいとアレだ。(Cython と C++ をミックスするときも同じ。)

何かというと、

1 from distutils import sysconfig
2 from distutils import ccompiler
3 
4 cc = ccompiler.new_compiler()
5 sysconfig.customize_compiler(cc)

という具合に customize_compilerすると、「煩雑なコンパイルオプションを色々自動でくっつけてくれて幸せ」なわけなんだけれど、「「Python にゆかりのあるものをビルドするため」に最適」が仇となるわけである。それが-Wstrict-prototypes

結構前から気にはなってはいたのだけれど、警告だし全く致命傷じゃないもんだからほったらかしにしていた。けどこれ、コンパイルするファイル数が何十・何百になってくると、煩くてしょうがない。ちゃんとしよ、と思った。

要するにこれ、

 1 >>> from distutils import sysconfig
 2 >>> import json
 3 >>> print(json.dumps(sysconfig.get_config_vars(), indent=1))
 4 {
 5  "AST_H_DIR": "Include",
 6  "HAVE_INET_PTON": 1,
 7  "HAVE_GETPEERNAME": 1,
 8  "HAVE_GETC_UNLOCKED": 1,
 9  # ...(snip)...
10  "CC": "gcc -pthread",
11  # ...(snip)...
12  "CFLAGS": "-fno-strict-aliasing -g -O2 -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes",
13  # ...(snip)...

これ(sysconfig.get_config_vars())に従う、ということ。この設定は Python 本体のコンパイル時に決まる。「Python本体のビルド方法と全くおんなじにせねばならぬ」から、というのが「Python にゆかりのある」場合の話。

けどゆかりがあろうがなかろうが、C++ するのに-Wstrict-prototypesはどっちみちいらない。

どうしたら一撃で回避出来るかなぁ、と探ってみたが、ちょっと乱暴だけれどこんなんでオッケー:

1 from distutils import sysconfig
2 if sys.platform == 'linux2':
3     sysconfig.get_config_vars()["CC"] = "g++ -pthread"
4     v = sysconfig.get_config_vars()["CFLAGS"]
5     v = v.replace(" -Wstrict-prototypes", "")
6     sysconfig.get_config_vars()["CFLAGS"] = v

setup.py の先頭でこんなことしておけば、あらゆるものがこれに従ってくれる。(Python 2.7 の話です。Python 3.x でどうかは調べてない。)