Monthly Archives: October 2013

PaperHouse で C のライブラリをコンパイルする

1 はじめに

前回では PaperHouse を使えば簡単に C から実行ファイルをコンパイルできることを説明しました.なんと実行ファイルのほかにも, PaperHouse を使えばライブラリ (スタティックライブラリや共有ライブラリ) も同様に簡単にコンパイルできます.

2 スタティックライブラリを作る

スタティックライブラリを作るときの面倒臭さって, .a ファイルを作るための gcc のオプションやコマンド (ar と ranlib) がすぐに思い出せないことです.

PaperHouse::StaticLibraryTask はスタティックライブラリをコンパイルするための rake タスクです.PaperHouse::ExecutableTask と同じく単純なインタフェースで,gcc のオプションやコマンドを知らなくとも簡単にスタティックライブラリをコンパイルできます.

次の例は hello.c から libhello.a をコンパイルする Rakefile の例です.何もむずかしいことはありません.

PaperHouse::StaticLibraryTask.new :libhello do |task|
  task.sources = 'hello.c'
end

rake libhello で libhello.a をコンパイルできます.必要なコマンドが自動的に呼び出されていることが分かります.

$ rake libhello
gcc -H -fPIC -I. -c hello.c -o ./hello.o
ar -cq ./libhello.a ./hello.o
ranlib ./libhello.a

PaperHouse::ExecutableTask と組み合わせれば,こうしてできたスタティックライブラリに実行ファイルをリンクするのも簡単です.

task :hello => :libhello

PaperHouse::ExecutableTask.new :hello do |task|
  task.ldflags = '-L.'
  task.sources = 'main.c'
end

PaperHouse::StaticLibraryTask.new :libhello do |task|
  task.sources = 'hello.c'
end

これを Makefile で書くとなると,少し本気を出さなければいけません.でも PaperHouse を使えばこのようにとてもお手軽です.

3 共有ライブラリを作る

共有ライブラリは PaperHouse::SharedLibraryTask です.スタティックライブラリと違って共有ライブラリではファイル名にバージョン番号が必須なので,.new の第二引数にバージョン番号を渡してください.

PaperHouse::SharedLibraryTask.new :libhello, '0.1.0' do |task|
  task.sources = 'hello.c'
end

rake libhello を実行してみましょう.

$ rake libhello
gcc -H -fPIC -I. -c hello.c -o ./hello.o
gcc -shared -Wl,-install_name,libhello.so.0 -o ./libhello.so.0.1.0 ./hello.o

何も考えなくても libhello.so.0.1.0 ができました.これで共有ライブラリでもスタティックライブラリでも何でも来いです.

4 おわりに

PaperHouse でスタティックライブラリと共有ライブラリをコンパイルする方法を紹介しました.次回は,Ruby の C 拡張モジュールをコンパイルする方法です.

Tagged ,

PaperHouseでCをコンパイルする

1 はじめに

PaperHouse は C のソースコードをコンパイルするための強力な Rake タスクライブラリです.Trema の一部は C で書かれていますが,Trema はこの C で書かれた部分をコンパイルするのに PaperHouse を使っています.

PaperHouse がコンパイルできるターゲットは次の 4 つです.

  1. 実行ファイル
  2. スタティックライブラリ
  3. 共有ライブラリ
  4. Ruby の C 拡張ライブラリ

今日はこのうち,実行ファイルをコンパイルする方法を紹介します.素の Rake も十分強力ですが,PaperHouse を使えばもっと簡潔に書けることを示します.

2 実行ファイルを作る

まずは一番単純な例から見てみましょう.あるディレクトリに *.c*.h があって,これらをコンパイルして実行ファイル hello を作るには Rakefile を次のように書きます.

PaperHouse::ExecutableTask.new :hello

なんとたったの一行です.PaperHouse::ExecutableTask クラスを使うと,次の 3 つの Rake タスクが自動的に使えるようになります.

rake hello
カレントディレクトリに hello という実行ファイルをコンパイルします.
rake clean
オブジェクトファイル (*.o) を消します.
rake clobber
実行ファイル (hello) とオブジェクトファイルをすべて消します.

もちろん,(再) コンパイルでは必要なファイルだけをコンパイルします.PaperHouse は賢くて,*.c と *.h ファイルの依存関係を解析して更新したファイルと依存するファイルだけをコンパイルしてくれます.まるでうまく書かれた make ファイルのようにです.

3 rake で書くとどうなるか

ためしに,まったく同じことをする Rakefile を Rake の標準機能だけを使って書くとどうなるでしょうか?

file :hello => FileList['*.o'] do
  sh "gcc -o #{t.name} #{t.prerequisites.join ' '}"
end

rule '.o' => '.c' do |t|
  sh "gcc -o #{t.name} #{t.source}"
end

CLEAN.include '*.o'
CLOBBER.include "hello"

6 行かかりました.これとまったく同じことが PaperHouse では 1 行だけでできるのです.

4 PaperHouse の特長

今まで見てきたように,PaperHouse は Rake で C をコンパイルするときに便利な gem です.素の rake が提供してくれる文法を使うよりも,もっと短く手軽に Rakefile を書けます.

大きな特長は Pure Ruby であることです.PaperHouse に似た Ruby のツールはいくつかありますが,それらは依存関係の解析に外部ツールの力を借りています.つまり,使うためには makedepend などの別ツールを別途インストールしなくてはなりません.

一方で,PaperHouse は依存関係解析を gcc の機能だけを使って行います.仕組みの詳細は省きますが,gcc や gcc から派生したコンパイラがインストールされていさえすれば,PaperHouse をすぐに使いはじめることができます.もともと C のプログラムをコンパイルしようとしているのですから,gcc がインストールされているのは当然ですね.

Pure Ruby なので Linux や Mac でも動作します.加えて,Ruby のメジャーバージョン (2.0, 1.9.3, 1.8.7) のすべてで動作します.

5 そのほかのオプション

上で見てきた単純な例のほかに,PaperHouse::ExecutableTask は次のようなオプションもサポートします.

PaperHouse::ExecutableTask.new :hello do | task |
  task.executable_name = 'hello'
  task.target_directory = 'objects'
  task.sources = 'sources/*.c'
  task.includes = 'includes'
  task.cflags = %w(-Wall -Wextra)
  task.ldflags = "-Llib"
  task.library_dependencies = %w(sqlite3 pthread mylib)
end
  • 実行ファイル名の指定 (タスク名と異なる場合)
  • ソースファイルやヘッダファイル,オブジェクトファイルを置くディレクトリの指定
  • コンパイルオプション (CFLAGS) やリンカオプション (LDFLAGS) の指定
  • リンクするライブラリの指定

このように,Makefile でできることはほとんど PaperHouse でもできます.しかもずっと簡潔に書けるのです。

6 おわりに

ちょっとした C のプログラムを書くときには,ゴリゴリと Makefile を書くかわりに PaperHouse を検討してみてください.小規模なプロジェクトであれば PaperHouse で十分な場面も多いはずです.ぜひ試してみてください.

Tagged ,