2014年5月16日金曜日

MacでBoostはどんな感じ!?

昔、Boostを使えるようにLinuxやらMacでビルドしたことがあります。(おそろしく時間がかかりました)
そういえば今の新しいMac(Mavericks)になってからgcc→clangに変わったので、どうやってBoost使えるようにしたものかと思って調べてみました。(c++第4版ではBoostが標準ライブラリになるもんだと思ってましたが、正式には発表されてないみたいだし、そもそも第4版って発効されたんだろうか?でもBoost使いやすくていいと思ってます。)

そうしたらどうも、今のMavericksのXcode5だと素直にはBoostはビルドできないらしい。問題なのはXcode5でインストールされるcコンパイラがclangで、libstdc++-4.2.1(実際、gccのバージョンを調べてみるとこういってきます)のため、4.3以降に実装されたstd::moveがなく、boostは当該関数があるのが前提で作られているらしく、ダメだとのこと。(がんばるなら、libc++をリンクするようにしたり、gccの最新版を別途インストールしないといけない。)

なんでこんなことになったのかというと、gnuがGPL v3を出したのが大元の原因らしい。(確かに数年前、OSSの方ではもめてましたね)gccがGPL v3にしたもんですから、これで仕事している人間たちはもっと縛りの緩いBSDライセンスなLLVM、clangを採用し始めたとのこと。(おかげでclangの開発が急に進みましたが)Linux kernelもv3は批判していて、未だにv2だったはずです。
でもLinux kernelはgccコンパイラでないとビルドできないようなgcc固有の機能を使っています。なんでgccコンパイラがGPL v3なのに、それを使っている(正確にはlibstd++に依存している)Linux Kernelがv2のままで居られるのかと思っていたら、gccのライセンスに抜け道が用意されていたらしく、gccでビルドしたものはv2でもいいよ(意訳)と書いてあるそうです。

さてここで本来のMacのBoostの問題に戻りますが、Macとしては新しいlibstdc++を採用したいが、GPL v3は採用したくない。そのためコンパイラをclangにしましたが、そうなるとlibstdc++-4.3からはGPL v3になるため、これを採用できない。という、風が吹けば桶屋、みたいな状況に陥っているようです。

まあclangの方が頑張ってくれれば問題はなくなるんですが、そもそもc++第4版の決定ってどうなったのよ?以前、c++第4版の決定稿の話を聞いた時は、これでしばらくコンパイラの実装が不安定になるなと悩んでいましたが、事態はそれとは別の方向に悩ましいことになってました。
(Boost関係とか実験するときは、しばらくLinuxでやるしかないようです。)

2014年5月7日水曜日

Raspberry Pi:cronの設定(その2)

さてcronで毎日決まった時間に動くようにしたプログラムですが、うまくいかないものがあります。/var/log/syslogに設定した時間になるとプログラムが起動したと記録は残るのですが、1分くらいすると異常終了しています。
/var/log/syslogを見ると、異常終了したと思われる時間に以下の様なログが残っていました。

May  7 18:46:52 raspberrypi /USR/SBIN/CRON[3380]: (CRON) info (No MTA installed, discarding output)


何かよくわかりませんが、”MTA”って確かメーラーのことだよね?なんかcronが異常をメールで送ろうとした?
調べてみると、Raspberry Piはデフォルトではメーラーが入っておらず、postfixを入れるといいよ、という記事が多くありました。

$ sudo apt-get install postfix

ただ記事を見てると、インターネットで使うための設定(アカウント名、パスワード等)が書いてありますが、こっちはそんな気はありません。上記コマンドで初めてpostfixをインストールすると初期設定が動き出してくれて、そこでlocalを選択できました。(インターネットなんかする気ないよ、ということ)
これで無事、異常終了してたプログラムも何が問題があったかをlocalでメールしてくれて、その続きの処理をしてくれるようになりました。(要は、最初に問題が見つかりメール送ろうとしたけど、それが送れなくて、プロセス自体が止まってしまっていた。問題は単なるワーニング・レベルで、無視してくれればよかった。)

2014年5月6日火曜日

Raspberry Pi:cronの設定

Raspberry Piは電源もたいしてくわなくて、ファンがなくても動作OKです。更にHDDがなくてもLinuxが動作するということで、1日中電源Onにしておくサーバーにするのにもってこいです。ただ外部記憶がmicroSDだけで(自分は32GBを使っています)、ファイルサーバーには使えませんし、CPUも大した性能がなく、Ethernetの口も基本一つしかつていませんから、Firewallにするわけにもいきません。
まあ何に使うかはともかく、電源入れっぱなしのマシンにして何がしかのサービスをさせようと思うと、定期的にプログラムを起動するための設定、crontabをちょっと調べてみました。

自分がcrontabのこと調べてた時は、/etc/crontabに定期的に動かしたコマンドを登録して、crondデーモンを再起動したもんですが、今はだいぶ変わりましたね。(便利になった)

  1. crontabの登録
  2. これは簡単で、以下のコマンドでOKです。
    $ crontab -e
    /etc/crontabはroot権限がないと編集できませんが、今はユーザー毎にcrontabが存在しており、それを自由に登録・削除できます。/etc/crontabはシステムに一つしかないファイルですので、ここにコマンドを登録するときは、当該コマンドを実行するユーザーも設定しないといけませんが、今は個々のユーザーがcrontabを持てるので、、上記コマンドで設定するときはユーザーの設定はいちいち必要ありません。(当然、設定しているユーザー権限で動作しますから)
    尚、editorはデフォルトで"nano"が動きますが、はっきり言ってこれは使いにくい!せめてviかemacsでやりたいところです。crontabの説明を調べると、起動時にどれを使うか問い合わせてくれるとか、後で変更できるとありますが、Raspberry Piではできないようです。従って汎用的な方法として.bashrcに以下の設定を追加します。
    EDITOR=emacs
    export EDITOR

  3. crontabの確認
  4. 以下のコマンドで自分用のcrontabの登録状況を確認できます。
    $ crontab -l

  5. crontabの場所
  6. さて肝心の個々のユーザーのcrontabがどこにあるかですが、以下の場所です。
    /var/spool/cron/crontabs/(ユーザー名)
    というファイル名で保存されています。crond自身は1分程度毎にこのファイルの変更状況を確認しているようで、特にcrondを再起動しなくても変更は反映されます。(そもそもcrontabは分単位でしかプログラム動作を設定できないので、これで十分です)
注意として、実行したいコマンド(特に自分で作成したプログラム)、ファイル等を指定するとき、なるべくフルパスで行った方が安全です。cronで当該コマンドが実行される時の環境(動いている時のカレントパスがどこなのか等)がよくわからないので、できるだけ依存性がないようにしておくべきです。

追記:
なぜcrontabの設定なんか調べていたかというと、Raspberry Piをネットラジオの録音サーバー(特定の番組を予約録音して、結果をmp3ファイルにする)にしたてようと目論んでいるんです。crontabで留守録音の登録をしてみて、うまくいきました。某サイトに録音スクリプトが公開されていたので(注:著作権的にグレーな気がしますので、詳しい場所は伏せておきます。探せばすぐに見つかります。)、それを使いましたが、以下のパッケージが必要で、apt-get installですべてインストールしました。
swftools
rtmpdump
libxml
wget
ffmpeg
lame
ちょっと困ったのが、1時間ほどの録音をした後、mp3変換にffmpegが動いているのですが、これが40分くらいかかってしまいました。サイズも56MBと結構なサイズになりました。とりあえず原理的には動くことがわかったので、ブラウザで録音設定ができるようなフロントエンドや、録音データを簡単にタブレットに転送できるような方法を考えないと。

2014年5月2日金曜日

Coin 3D:現状とビルド

Coin 3Dってご存知でしょうか?3DのGraphics Libraryですが、20年位前その分野で有名だったのがSGIというコンピュータ会社でした。そこが今では業界標準になっているOpenGL(大胆にも、GLはGraphics Libraryの略です)を作り、更により上位のライブラリとしてOpenInventorを作りました。(Inventorは1995年くらいだったかな?)
当時のSGIは非常にバカ高いWS(Work Station)を販売しており、そこでしかOpenInventorは使えませんでした。そのとき、有志で互換のライブラリを作ろうと出てきたのがCoinでした。(皆、興味がなくなったのかぐぐっても、情報がないですね。)

1.概要
2009年頃書いていたブログ(今とは別の所で書いてました)にその当時のCoinの状況を書いてました。
SGIの経営が2000年を越えてしばらくしてから怪しくなり、Inventorの権利を別会社に販売したり、OpenInventorと命名して(Openを頭文字に入れた)、ソースを公開していました。(2005年くらいだったかな。OpenInventor2.1.5が最後に公開されたソースコードで、当時RedHat9でビルドができました。)
結局SGIは3Dグラフィクス分野からは手を引き(日本SGIに確かその分野を譲渡し、NECが資本を注入してました。)、完全にOpenInventorのソースコードが中に浮いてしまった状態になりました。(その前にInventorのライセンスを買った会社は今でもOpenInventorのメンテナンス、といっても新しいプラットフォームへの対応、バグとり程度しかしてませんが、これがまた高い!こちらのソースコードは非公開なので、全く独立にメンテされています)
2009年の2、3年前にCoinがフリーになったOpenInventorのソースコードを使うことの許可をSGIに得て(それまではAPI定義だけを元に、独自の実装をしていた)、メンテナンスを行うという発表を見た記憶がありました。その後、2009年に調べてみたら、なんかCoin 3Dがどこかの会社(資源探査会社?)に買い取られ、Qtのようなダブルライセンスになっていました。当時、CentOS5でビルドしてみましたが、あっさりビルドできて動いた記憶があります。(ただ見た目がまだかなり、本物のOpenInventorとは違っているところがありました。はっきりいって「いけてない」感じのデザインでした。)

さて2014年現在ですが、なんとCoin3Dはその会社が放棄していました!!(2012年)商売にならないと判断されたのでしょう、現在では一部の有志だけで公開されているようです。(JIRAで有名なAtlassianが行っているSourceForgeのようなサービスでプロジェクトを公開していました。リポジトリはgitではなく、Mercurialを使っていました。そこではwikiサービスも行っており、JIRAのようなタスク管理も動いていましたが、活動があまり活発ではありませんでした。)
従って、ソースコードも2012年から更新されていないようです。

2.Coin 3Dのビルド
さて現状のバージョンはCoin-3.1.3となっています。これをDLしてきて、以下の環境でビルドしてみます。

・Ubuntu 13.10
・g++-4.8.1

(1)configureでのエラー
何も考えずに、no-optionでconfigureすると以下のエラーがでて、configureができなかった。cc_debugerror_post()の関数定義で、先行定義してあるデバッグ用関数において、gcc-4.7以降ではtemplateの解釈が変わったらしく、namespaceの範囲解釈が変わり問題がでるようになった。
 元々、trickyな定義がしてあったらしい。解決方法が見つからないので、debugをスルーするようにした。

$ configure --disable-debug

これで当該エラーはでなくなり、ビルドができるようになった。

(2)g++のバグ
ビルドをしてみると、以下のエラーがでた。

In file included from ../../../Coin-3.1.3/src/base/dict.h:31:0,
from ../../../Coin-3.1.3/src/fonts/freetype.cpp:142:
/usr/include/c++/4.8/cstdlib: In function ‘long long int std::abs(long long int)’:
/usr/include/c++/4.8/cstdlib:174:20: error: declaration of C function ‘long long int std::abs(long long int)’ conflicts with
abs(long long __x) { return __builtin_llabs (__x); }
^
/usr/include/c++/4.8/cstdlib:166:3: error: previous declaration ‘long int std::abs(long int)’ here
abs(long __i) { return __builtin_labs(__i); }


どうもabs()関数の多重定義に関するエラーらしい。ただ問題が、abs()関数を使うところではなく、abs()関数をinline定義しているcstdlibをincludeしているところで発生しているため、どう対処したらいいのかがわからない。

英語でぐぐってみたら、gcc-4.8のバグで、cstdlib(c++用)がstdlib.h(c用)を含めてマクロ定義を多重に読み込むのを防ぐときのバグらしい。(cで書かれたプログラムをc++で流用するときが多分にあり、そのとき両方がincludeされることが多々発生するが、同じマクロ定義が行われていることが多い。その問題を解決するのにg++側でバグがでているっぽい)
別のプロジェクトのブログに解決法として、両方includeしているようならcstdlibをやめろ(stdlib.hだけにしろ)というのがあったので、ソースを一部修正してみると、ビルドが先に進んだ。
(src/base/dict.h:31  cstdlibのincludeをコメントアウトした)

(3)namespace指定の問題
更にビルドが進むと、以下のエラーがでた。

g++ -DHAVE_CONFIG_H -I../../include -I../../../Coin-3.1.3/include -I../../src -I../../../Coin-3.1.3/src -D_REENTRANT -DNDEBUG -DCOIN_DEBUG=0 -DCOIN_INTERNAL -g -O2 -W -Wall -Wno-unused -Wno-multichar -Woverloaded-virtual -MT glyph.lo -MD -MP -MF .deps/glyph.Tpo -c ../../../Coin-3.1.3/src/fonts/glyph.cpp -fPIC -DPIC -o .libs/glyph.o
../../../Coin-3.1.3/src/fonts/glyph.cpp:41:12: error: ‘std::free’ has not been declared
using std::free;


std::freeというnamespaceがg++-4.8にはないらしい。とりあえずコメントアウトしてみる。

 free()はstdlib.h内に定義してあるが、includeしてないせずにnamespaceの定義だけでエラーを逃げようとしたらしい。他にもmallocでも別の近い箇所でエラーでる。
どうも(2)で述べた、stdlib.hとcstdlibの多重includeで問題がおきて、一部ソースではstdlib.hをincludeするのをやめ、using std::freeとかのnamespace定義で逃げようとしたらしいが、それが問題になったらしい。(先に、cstdlibのincludeをコメントアウトしたせいか?)

 かわりに#include <stdlib.h>してやれば先に進んだ。
結果として、これでビルドはパスし、make installができた。(/usr/local以下にヘッダ、ライブラリはインストールされた)


3.サンプルプログラムの作成
さて実際にビルドが成功したかを確認するために、サンプルプログラムとして、Inventor mentorの最初にある、Red Coneをコンパイルしてみます。
しかし、これだけではビルドができません。よく見たら、Coin-3.1.3のtarボールにあるのはOpenInventor本体だけであり、それをwindow上に表示するためのSoXt(WindowsならSoWin等)がありません。Coin3DのHPに別途、SoXt-1.3.0があり、それをインストールする必要があります。

(1)configureでのエラー
何も考えずにconfigureすると、Coinと同じようにcc_debugerror_post()の関数定義でエラーがでました。同じように、--dsiable-debugオプションで逃げます。

(2)実行時にエラーがでる
これでSoXtのビルドは成功、インストールできました。しかしサンプルプログラムを実行すると以下のエラーがでます。

Coin error in SoXtGLWidget::buildWidget(): SoXt does not support detecting best visual/colormap without the Xmu library (yet)

よくわかりませんが、ビルド環境を調べてみるとXmuのランタイムは入っていますが、開発環境(libxmu-dev)までは入ってませんでした。試しにインストールしてSoXtを再ビルドしてみましたが、状況はかわりません。

このエラーを出している箇所を調べてみると、場所は、SoXtGLWidget.cpp:1064らしい。

#ifndef HAVE_LIBXMU
SoDebugError::post("SoXtGLWidget::buildWidget",
"SoXt does not support detecting best visual/colormap without the Xmu library (yet)");
exit(1);
#else // HAVE_LIBXMU


内容的には、Xmuライブラリを持っていなかったらとのフラグでここに入っているが、当該環境にはXmuライブラリはインストール済みである。configureに問題があるらしい。
config.logを見ると、環境調査の中で以下の箇所で問題がでていた。

configure:22291: g++ -o conftest -g -O2 -W -Wall -Wno-unused -Wno-multichar -Woverloaded-virtual\
  -DNDEBUG -DSOXT_DEBUG=0 -DSOXT_INTERNAL      conftest.cpp -lXmu -lXext  -lSM -lICE -lX11  -ldl\
  >&5
conftest.cpp:31:41: fatal error: X11/Xmu/Xmu.h: No such file or directory
                 #include <X11/Xmu/Xmu.h>
                                         ^
compilation terminated.

おそらくこのエラーのせいで、Xmuライブラリが環境に存在しないと判断されたらしい。しかしなぜこんなエラーが出てくるのか不明。(当環境には、当該位置にXmuは入っている)
再度、通常のターミナルでSoXtをmakeし直しました。(前回はおそらくemacs内のshellで行っている。通常、ログをあとで確認するためよくemacs内のshellでビルドをしているくせがついている。)
するとXmu関係のエラーがconfig.log内にでなくなり、SoXtを再インストールしたら動きました!


4.サンプルプログラムの実行
2個ほど、実行結果を示します。

(1) HelloCone
まずはmentorの最初にでてくる一番シンプルなものです。

画面の真ん中に、赤い3角錐が表示されるだけです。

(2)ExaminarViewerの実装
最初のCoinにはまだ実装がなかったんですが、OpenInventorではとても便利なViewerだったExaminar Viewerです。

ぱっと見、大して変わらないように見えますが、このViewerではマウスで表示中のモデルを自由に視点を回したり、拡大/縮小ができます。右端の一文字のボタンが何か昔のSGIの実装とは違いますが(確かアイコンで機能が表示されていたはずなんですが、一文字になってますね)、とりあえず動作には問題がありません。

と、まあ一応は動くようです。(g++周りの実装が変わったことによるエラーには少し悩みました。昨年末、やっとc++第4版の仕様が確定したらしいという話を聞いたせいか、多少実装に変更があったようです。)

Ubuntuも14.04LTSが発表されたところで、今の環境だと「アップデートするか?」と毎回聞かれますが、こんな時にg++のバージョンが変わってしまったら訳がわからなくなりますから、そのままにしてあります。