猫でもわかるWebプログラミングと副業

本業エンジニアリングマネージャー。副業Webエンジニア。Web開発のヒントや、副業、日常生活のことを書きます。

libprotoc 3.0.0 から libprotoc 3.3.2 にアップデートしたらコンパイル時の namespace 指定が効かなくなって GPBMetadata が生成されるようになった

状況

PHPで書かれたプロジェクトで protocol buffer を利用していた。最初は libprotoc 3.0.0 を使用していたが、 これを 3.3.2 にバージョンアップした瞬間、 コンパイルオプションの namespace が効かなくなり、3.0.0 とは異なる成果物が生成されるようになった。libprotocのバージョンを 3.0.0 に落として過去のものと同じファイルが生成されるようにしたい。

libprotoc 以外の環境

protoファイルから生成されるphpのnamespaceが突然変わった

もともとは libprotoc 3.0.0 を利用し、以下のページを参考にprotoファイルをコンパイルしていた。

53ningen.com

stanley-cheung/protobuf-php を利用し、以下のようなオプションでphpファイルの生成をしていた。

$ ./vendor/bin/protoc-gen-php.php -Dnamespace=projectname.dest.protobuf -Dmultifile -o ./ -i . target.proto

このコマンドでコンパイルすると、 target.protoコンパイルされて projectname/dest/protobuf/target.php のような1つのファイルが生成される。

しかし、ある時 brew update したら brew で入れていた libprotoc のバージョンが 3.0.0 から 3.3.2 に上がり、 -Dnamespace のオプションが効かなくなった。常に proto ファイルで指定された namespace にファイルが生成されるようになり、さらに GPBMetadata というファイルも生成されるようになった。既に過去に生成されていたphpファイルも存在しているため、過去のものと統一性を持たせるために libprotoc のバージョンを 3.0.0 に下げ、 -Dnamspace オプションが効くようにすることで、過去と同一の成果物が生成されるようにする。

手順

まず既存のlibprotocを削除する。brewで入れたのであれば brew uninstall protobuf 的なことをしてもいいが、今回はbin以下にあるファイル名をrenameすることで解決した。ちなみにrenameするだけの場合、再び brew update などをすることで最新バージョンに書き換わってしまうかもしれないので注意。

$ protoc --version
libprotoc 3.3.2

$ which protoc
/usr/local/bin/protoc

$ mv /usr/local/bin/protoc /usr/local/bin/protoc332 # 移動後の名前はなんでもよい

$ protoc332 --version
libprotoc 3.3.2

3.0.0 の libprotoc をダウンロードする。3.0.0 に限らず、 https://github.com/google/protobuf/releases から欲しいバージョンのバイナリをダウンロードしてくれば良い。今回は 3.0.0 なので、 Release Protocol Buffers v3.0.0 · google/protobuf · GitHubprotoc-3.0.0-osx-x86_64.zip をダウンロードして PATH が通っている場所に置いた。

$ cd /usr/local # 場所はなんか適切っぽい場所にしてください
$ wget https://github.com/google/protobuf/releases/download/v3.0.0/protoc-3.0.0-osx-x86_64.zip
$ unzip protoc-3.0.0-osx-x86_64.zip
$ ln -s /usr/local/protoc-3.0.0-osx-x86_64/bin/protoc /usr/local/bin/protoc
$ protoc --version
libprotoc 3.0.0

これで任意の protoc のバージョンをダウンロードできるので、あとは元の手順通りコンパイルすれば全く同じphpファイルが生成できる。

さいごに

もしかしたらnamespaceのオプション名が変更になっただけで、正しくしていすれば 3.3.2 でも同じものが生成できるのかもしれないが、今回は「過去のものと同じバージョンでコンパイルする」ことを目的として libprotoc のバージョンを下げる方法を紹介した。