BizStationブログ

ビズステーション株式会社の公式ブログです。

C++ クロスプラットフォーム開発

しばらく日が空いてしまいましたが、相変わらず元気に Transactdに励んでいます。もうすぐTransactd 2.0 がリリースできそうですが、今回はC++コンパイラーのお話しです。
Transactdの基本ライブラリ開発はC++ですが、OSはWindwosとLinuxMac OS XコンパイラーはVisual Studio, C++Builder 32Bit 64Bit, Clang, GCCマルチプラットフォーム、マルチコンパイラです。でもこれをワンソースでコンパイルできています。日々これらと格闘していると色々見えてきたのでその辺を書き留めておきたいと思います。

文字コード

LinuxMac OS Xではutf8で書いていますが、定数に日本語文字列を使うときは、ソースファイルを必ずutf8 BOM付で保存します。LinuxではBOMなしが標準ですが、Visual Studio (VS)はBOMなしを理解してくれないのでBOM付にします。(4.3以前の古いGCCはBOMを読めないので注意)
WindowsではUNICODEが標準ですので、文字列は通常ワイド文字として扱います。WindowsLinuxの両方に対応するために、文字列はすべて _T _TCHARマクロを使い、Linux用のtchar.hを作成して両方に対応させています。最初は少し面倒ですが、慣れればあまり大した問題ではないですね。

template

テンプレートへの対応は、C++Builder 32Bitが一番おバカで、これでコンパイルが通ればあとのコンパイラーは何とかなります。ですので、最初のコンパイルはほとんどC++Builder32です。このコンパイラーのテンプレート解析のクセはVSに通じるものがあって、Borlandの開発者はVSでコンパイルでできてC++Builderでできないものを潰していったのでは?と感じるものがあります。
GCCとClangは似ているようでそうでもなく、VSとも違い3つのコンパイラーはそれぞれ我が道を行っています。そうは言ってもC++ですので、それぞれに意味のあるエラーを吐いてくれます。あちらをとればこちらがダメといったことはかなり少なく、普通のテンプレートほとんど共通で使えます。

boost

boost様々です。プラットフォームに依存する部分をboostで書けばワンソースでマルチプラットフォームが簡単です。thread mutex socketやfile TESTなんかもそうです。ただ、C++Builder32はboost 1.39までしかサポートされていないので、それ以上の機能を使うときだけ、C++Builder32では少し異なる実装をする時があります。GCC VS Clangでは最新のboostが使えます。

デバッガ

Visualなデバッガに慣れてしまっていると Linuxでのgdbは悲惨です。Windowsでのデバッグの3倍くらいの時間がかかってしまいます。デバッグにはC++Builder32がお勧めです。理由は

  1. コンパイルがとても速い
  2. 充実した機能(実行コマンドライン、Visualで変数値のツールチップ表示やメモリダンプ、呼び出し履歴など)
  3. 安定動作

何よりも、コンパイルが早いのがデバッグには最高です。直す -> コンパイル -> 実行 -> デバッグ のサイクルをとても早く回すことができます。機能も欲しいものはほとんど揃っています。唯一、条件付きのブレークポイントが設定できませんのでif文を入れてブレークしたりしています。
gdbLinuxでの動作に問題があるときにたまに使うくらいであまり頻繁には使いません。Linuxではデバッグ用のコード埋め込みやダンプのほうがやり易い場合も多くあります。
C++Builder 64Bit Clangのデバッガはリモートデバッグに似ていて、IDEとの間に別プロセスのエージェントが入っています。今のところこれがハングしてしまうことが多く、一応使えますが、安定して快適にとうところにはなっていません。

コンパイラとプラットフォームの違いの吸収

コンパイラによって Cライブラリやpragmaなどが違っています。また、プラットフォームでパスのセパレータやスレッドローカルストレージなど様々なものが異なっています。
これらは、それぞれ、compiler.hcrosscompile.hにまとめ、マクロでの切り替えや不足する関数を補って、通常のソースは共通のコードで書けるようにしています。あまりきれいなソースではありませんが違いを埋めるマクロが詰まっていて、苦労の逸品?です。(transactdのソースにありますのでGPLv2で使えます。)

最適化

C++Builder32を少しお勧めしましたが、最大の欠点は実行速度が遅いことです。VSの1.5倍くらい遅くなります。PHPRubyからVSでコンパイルしたTransactdクライアントを使うと、C++Builder32のネイティブより高速にDB処理ができます。ただ実際はDB処理だけではありませんので、総合的にはC++Builderの方が早くはなると思いますが、糊(スクリプト言語)の実行速度は下で働くC/C++ライブラリの最適化と、どれだけライブラリ呼び出しだけで済ませるかにかかるかと思います。スクリプト言語でゴリゴリ書くとスローになってしまいます。(TransactdのPHP,Ruby,ActiveXはすべてVSかGCCですのでご心配なく)
64Bit Windows上のVSとClangではVSの方が数パーセント速そうで、やはり総合的に見てVSはベターなコンパイラです。

まとめ

コンパイラ比較になってしまいましたが、個人的な好き嫌いで違いをまとめておきます。

コンパイラ 実行速度 コンパイル速度 デバッグしやすさ IDEの好み
GCC 使ってない
VisualStudio △(遅く感じる)
Clang(C++Builder64)
C++Builder32
何か参考になればいいですが。

次は、Transactd 2.0に乞うご期待!