百日半狂乱

Shut the fuck up and write some code!!

googletestを/usr/local/にインストールするシェルスクリプト

発声練習:Intel C/C++ を用いた Google Test環境を準備するを参考にしてgoogletestのセットアップを行うシェルスクリプトを書いた.

ホームディレクトリにソースを落としてきて、コンパイルした後に/usr/local/に必要なヘッダとライブラリをcpしているだけ.

cmakeが必要なので、なければ予めパッケージを落としてくる.

gtestを/usr/local以下にインストール/アンインストールするシェルスクリプト

googletest自体については、googletest入門ガイドが翻訳されている.

こいつを使ってTDDを実践したいんだけど、ビルドプロセスやテストの自動化で永久にyak shavingやってる、二年くらい.

2014/2/6追記:googletestに関して調べたことメモ

fused source files

エンジニアのソフトウェア的愛情:googletest1.5.0の使い方・その1:ビルドする

どうも、1.5.0からテストをビルドする度にgoogletestも再コンパイルせよという方針らしい.

エンジニアのソフトウェア的愛情:Google Testをインストール、しないですませる方法

それで、毎回再コンパイルするってどうすんのって話になる.

どれを使うの?って話は1.5.0から追加された「fused source files」で解決する.

リンク先にある通り、二つのソースと一つのヘッダをプロジェクトに絡めるだけで、テスト環境が手に入る.

手元の環境が仮想環境だった場合、コンパイルに時間がかかるのが辛い.

問題ないなら、/usr/local/にセットしたらライブラリのリンクですませたい.

googletest付属のサンプル

どうやって毎回再コンパイルするの?って話は同伴されているサンプルテストをビルドするMakefileを見ればわかる.

このMakefileの読み方とgoogletestについて素晴らしい解説を行っているエントリを見つけたのでメモ.

minus9dの日記:googletestを使いこなす

minus9dの日記:googletestに付属するサンプルを読み解く

リンク先ある解説図を見れば、/usr/local/以下にセットしたライブラリに何が含まれているかが一目瞭然.わかりやすいなぁ.

二十五日半狂乱、11日目(の分)の記事

nmコマンドでC/C++のシンボルテーブルを見る、C++の名前マングリング、"C"リンケージ、あるいはリンカに関するメモ

前回(g++)前々回(gcc)のサンプルコードを使ったC++のマングリングや"C"リンケージに関するメモ.

nmコマンドでサンプルコードのシンボルテーブルを覗いた後に、C++からCの関数を呼び出す場合のサンプルコードを示す.

特にリンケージ周りの説明は正確性を欠いているやもしれませんのでご容赦下さい.より詳細な説明は参考リンク等を参照して頂ければと思います.

nmコマンド

nm は、UNIXや類似のオペレーティングシステムに存在するコマンドであり、バイナリファイル(ライブラリ、実行ファイル、オブジェクトファイル)の中身を調べ、そこに格納されているシンボルテーブルなどの情報を表示する。デバッグに使われることが多く、識別子の名前の衝突問題やC++の名前修飾の問題を解決する際に補助として用いられる。

GNUプロジェクトでは、高機能の nm プログラムを GNU Binutils パッケージの一部として提供している。この nm コマンドは他のツールと同様に特定のコンピュータ・アーキテクチャとバイナリフォーマット向けにコンパイルされているので、セキュリティ専門家は疑わしいバイナリファイルを調査するためにネイティブでない nm コマンドを事前に取り揃えておくことが多い。

Wikipedia - nm(UNIX)

今回はこいつを使って、サンプルコードのコードのシンボルテーブルを見たり、C++からCの関数を呼び出す場合に起こる問題等について見ていく.

続きを読む

C/C++の関数プロトタイプ、暗黙ルールデータベースの話(その2)

前回の記事で公開したMakefileでは、gccコンパイルオプションに-Wallを付けていなかった.

極めて非人道的である.

現在Makefileを修正してコンパイル時に-Wallを付けるようにしたが、そのままmakeを叩くとコンパイラにしっかり警告を食らった.

run.c: In function ‘main’:
run.c:4:2: warning: implicit declaration of function ‘print_hello’ [-Wimplicit-function-declaration]

これは、前回のコードではmain関数でprint_hello()を呼び出しているが、それに先立って行うべき関数のプロトタイプ宣言を行っていないからである.

しかし、gccでは警告を食らうだけで、コンパイルは通ってしまう.

関数プロトタイプ(Function prototype)

Cで、もといgccで、関数プロトタイプがなくてもコンパイルが通るのは以下の理由による.

関数が事前に宣言されていない状況で、左括弧付きで式の中に現われた場合、その関数は暗黙のうちに int を返すものと判断され、引数については何の想定もなされない。

Wikipedia - 関数プロトタイプ

Wikipediaにも書いてある通り、書かない場合に問題が発生するので、基本的に関数プロトタイプを省略してはならない.

C++ではコンパイルが通らない

C++では、もといg++では、そもそもコンパイルが通らない.

前回のMakefile中の変数CCをg++にしてmakeを叩くと警告が出るだけでコンパイルが通ってしまうgccとは違って、コンパイラがエラーを吐く.

run.c: In function 'int main(int, char**)':
run.c:4:14: error: 'print_hello' was not declared in this scope
make: *** [run] Error 1

どうもg++では、関数プロトタイプが必須らしい.

g++でコンパイルが通るようにする

以下は、前回のコードをC++(g++)に合わせて若干変更したもの.

makeでライブラリ(.a)のビルドを管理するサンプル(g++.ver)

前回と違って.cファイルを.ccファイルとした上で、hello.hに関数プロトタイプを追加し、run.ccでhello.hを#includeするようにしている.

暗黙ルールデータベースの活用

上記のC++バージョンのコードは、Makefile前回のCのMakefileと少し違う.

ここではそれぞれのMakefileの記述が暗黙ルールデータベースにどのように作用しているかを比較してみることで、もう少し暗黙ルールデータベースに対する理解を深める.

続きを読む

makeを使ったライブラリのビルド管理と暗黙ルールデータベースの話

CでもC++でも良いんだけど、コードが大きくなってくるとファイルの分割を考え始める.

追記(204/1/30):このままコンパイラをg++にするとコンパイルが通らなかった.また、-Wallオプションを付けないというとんでもないことをしている.その辺のことをこちらの記事に書いたので併せて参照をば.

例えば以下のようなことをしたいと考えたとする.

  1. ライブラリとなるソースコード(hello.c)をコンパイルして、arコマンドで静的ライブラリ(hello.a)を作る.
  2. ライブラリを呼び出すソースコード(run.c)のコンパイル時にライブラリをリンクして実行ファイルを生成する.

これらを手でやろうと思うとこれだけでもう大変なのでmakeを使う.

makeでライブラリのビルドを管理する(サンプル)

これでおしまいにしようかと思ったけど、なんでこれで上手く行くのか毎回忘れるので簡単にまとめることにした.

今回はこのサンプルを使って、暗黙ルールデータベースを見てみる.

追記(2014/1/24):libhello.a: libhello.a(hello.o)というのは決して一般的な記法ではなく、アーカイブファイル用の記法なので注意(こちらを参照).

続きを読む