2012年10月7日日曜日

7-Zip で、ファイル名が UTF-8 エンコードされた zip ファイルを生成する方法

備忘録

Windows 上で、ファイル名にマルチバイト文字を含む zip ファイルを作成し、iTunes 経由で iPad の GoodReader に転送して、GoodReader で解凍すると、ファイル名が文字化けする。
理由は単純で、Windows 上で zip ファイルを作成すると、デフォルトでは、ファイル名が、cp932 (Shift-JISかも・・・)でエンコードされてしまうため。
および、iPad上では、(linux も)UTF-8 でファイル名が、エンコードされていることを、前提にしているのため。
したがって、逆もまた真なり。
解決策としては、いくつか考えられる
まず、ファイル名を UTF-8 でエンコードする圧縮形式を利用する場合、7zip 形式などがあるが、残念ながら GoodReader が未対応。
次の策は、、linux 上で圧縮する。これでもいいかも。試してないけど。
最後に、Windows 上でも、ファイル名を UTF-8 エンコードしてくれるツールを利用することだが、今回はこの方法にした。利用するツールは、7-Zip 。

環境

Windows 7 Professional 64bit SP1
7-Zip 9.28 (x64 edition) alpha バージョン

実施手順

7-Zip はインストール済みとする。

圧縮対象(ここでは、books ディレクトリ)を右クリックし、コンテキストメニューの「7-Zip」⇒「圧縮...」を選択。


「書庫形式」を「zip」に設定。
「パラメータ」に「cu=on」を設定。
「cu」パラメータの説明は、「7-Zip uses UTF-8 for file names that contain non-ASCII symbols.」となっている。つまり、ASCII 文字以外が含まれている場合に、ファイル名を UTF-8 エンコードする。

ちなみに、この「パラメータ」というのは、コマンドラインの「-m」スイッチに指定するもの。「cu」パラメータは、 Zip 形式のときに有効となる。
詳細は、ググるか、ヘルプを参照。

最後に、「OK」ボタンを押下。

これで、ファイル名が UTF-8 エンコードされた zip ファイルが作成される。

Windows 上で確認する場合は、次のようにする。



zip ファイルを右クリックして、コンテキストメニューの「プログラムから開く」⇒「エクスプローラー」を選択。



エクスプローラーでは、cp932 でエンコードされている前提で、ファイル名を表示するため、UTF-8 エンコードされているファイル名は、見事に文字化けして見える。

この zip ファイルを、iTunes 経由で、GoodReader に転送し、解凍すると、見事に元のファイル名が、復元される。

ちなみに、7-zip で開くと、正常なファイル名で表示される。

2012年9月22日土曜日

ファイル選択ダイアログを開くとフリーズ(反応無し)になる元凶を見つけたよ

はじめに

最近、新マシンを新調し、環境構築をせっせとしているのだが、Exact audio copy (EAC) や Chrome などで、ファイル選択ダイアログを開くと、選択しても、しなくても、×ボタンで閉じたときでさえ、毎回フリーズして、アプリケーションが、応答しなくなったり、強制終了となる事象が発生して困っていた。
今日、その元凶が判明したので、さらしておく。

注意事項

今回の手順を実行すると、最悪で、起動不能になる場合もありえる。
実施は、くれぐれも自己責任で。

動作環境

Windows7 Professional 64bit SP1
CPU:AMD FX(tm)-8150 Eight-Core
メモリ:16GB

原因特定に利用したソフト

ShellExView
システムにインストールされている、シェルエクステンション(シェル拡張)を、一覧表示して、個別に機能を有効・無効化できるソフト。

元凶

DAEMON Tools Pro (DT Soft Ltd)

シェル拡張名:Image Catalog
バージョン: 4.40.0312.0221
ファイル:D:\appli\DAEMON Tools Pro\DTShl64.dll
ファイルサイズ:696,128 バイト

TortoiseSVN

バージョン:1.7.9-64bit

TortoiseGit

バージョン:1.7.12.0-64bit

特定方法

同様の現象を Google 先生に問い合わせると、どうやら腐ったシェルエクステンション(シェル拡張)が、原因なことが多いとか。
であれば、アヤシイものを、片っ端から無効にして、確かめるしかない。
そこで ShellExView の登場である。

実際の使用方法は、いたって簡単。
無効化したいものを選択し、右クリックしてコンテキストメニューから「Disable Selected Items」を、選択する。ただし、Microsoft のものは、避けたほうがいい。Microsoft 以外のものは、背景がピンク色になっているもので、一覧の「Microsoft」項目が「No」になっている。
再起動して、現象が発生するかを確かめる。
以上。

対処方法

DAEMON Tools

元凶を無効化する。

TortoiseSVN

設定を開き、「アイコンオーバーレイ」を選択。
「アイコンオーバーレイ/状態表示列」で、「エクスプローラー上でのみオーバーレイとコンテキストメニューを表示」チェックボックスにチェックを付ける。

TortoiseGit

TortoiseSVNと同様の対処を行っても、改善されず。
シェルエクステンションの無効化しかないかも。
でもそれだと、インストールする意味がまったくないよ。

愚痴

率直に言うと、「またおまえか!」って感じです。ほんとに、DAEMON Tools には、マルウェア騒動以来、悪いイメージしかない。
バンドル版なので、アップデートもできないし、アップデートダイアログで表示される、金払って延長しろってボタン以外、×ボタンも閉じるボタンも、数秒間無効化されて押せないし。
ほんっっっとに、感じ悪い。そういうメンタルは、有料版ユーザに対しても、変わるとは思えない。
腹が立ってきたので、アンインストールすることにする。
こういう下種な小細工は、競合がいない場合にのみ、有効なんだよ。
同じ金を払うなら、平均より上の別のソフトにするに決まってる。

と、悪態をついてはみたが、SVN 64bit版や Git 64bit版などのシェルエクステンションを使用しているものが、けっこう駄目になっていることを考えると、Windows7 が悪い気がしてきた。しかも 64bit 版特有の問題かもしれない。仕事場で使っている Windows7 32bit 版では、問題が起きていないし、 Vista 64bit 版 SP2 でも、こんなことはなかった。
現象から察するに、ファイルエクステンションや、ファイル選択ダイアログの仕様が変わってるのかもしれない。
しかし、いくらなんでも、アプリもろとも強制終了とか、ありえないと思う。
やっぱり Windows の SP1 は、ベータ版ってことだね。

2012年9月17日月曜日

Windows 64bit 用の ffmpeg をビルド

はじめに

ちょっと悶絶したくて、Ubuntu 上のクロスコンパイル環境で、Windows 64bit 用の ffmpeg をビルドしてみる。
ライセンスの関係で、配布できないものになるので、注意。

ビルド方法は、偉大なる先人である、「Linux日記: MinGWでx264、ffmpegをビルド」ページをマルパクリ・・・。ありがたや、ありがたや。

make に付いている -j6 は、並列ビルドするオプション。コア数 * 1.5 がいいとかなんとか・・・。場合によって、undefined などのエラーが発生するので注意。
CFLAGS などに指定してある -pipe は、テンポラリファイルではなく、パイプを利用して、メモリを多く使用する代わりに、コンパイルを高速化するオプション。

なお、ビルド手順については、思考錯誤などの手戻りで、ビルド順があやしいので、近々に検証する予定。

【2012/09/19】 ビルド手順の検証完了。やっぱり間違っていた。3回ぐらいやらないと、まともにならないな。手順を見直して、不要なライブラリが削れた。
ついでに、パッチをすべてアップロードした。パッチを当てるときは、解凍したディレクトリに cd してから「patch -p0 < パッチファイル」のようにする。
Blogger のせいなのか、タブ文字がスペース文字に置き換わってしまい、パッチをアップロードせざるを得なかった。

利用したソース

zlib (zlib-1.2.7.tar.bz2)
bzip2 (bzip2-1.0.6.tar.gz)
XZ Utils (xz-5.0.4.tar.bz2)
SDL (SDL-1.2.15.tar.gz)
gpac (gpac-0.5.0.tar.gz)
ffmpeg
ffms2
x264
OpenSSL (openssl-1.0.1c.tar.gz)
libpng (libpng-1.5.12.tar.gz)
libtiff (tiff-3.9.6.tar.gz)
libjpeg-turbo (libjpeg-turbo-1.2.1.tar.gz)
lcms2 (lcms2-2.3.tar.gz)
lame (lame-3.99.5.tar.gz)
faac (faac-1.28.tar.bz2)
libogg (libogg-1.3.0.tar.gz)
libvorbis (libvorbis-1.3.3.tar.gz)
libtheora (libtheora-1.1.1.tar.bz2)
libspeex (speex-1.2rc1.tar.gz)
opencore-amr (opencore-amr-0.1.2.tar.gz)
openjpeg (openjpeg_v1_4_sources_r697.tgz)
xvidcore (xvidcore-1.3.2.tar.bz2)
gsm (gsm-1.0.13.tar.gz)
rtmpdump
libvpx (libvpx-v1.1.0.tar.bz2)
libfdk-aac

未完遂のライブラリ

orc (orc-0.4.16.tar.gz)
libschroedinger (schroedinger-1.0.11.tar.gz)



依存ライブラリのビルド(1週目)

zlib

CFLAGS="-pipe -O2" \
CXXFLAGS="${CFLAGS}" \
CC=x86_64-w64-mingw32-gcc \
AR=x86_64-w64-mingw32-ar \
RANLIB=x86_64-w64-mingw32-ranlib \
LDSHAREDLIBC="" \
PKG_CONFIG_PATH=/usr/x86_64-w64-mingw32/lib/pkgconfig \
./configure --prefix=/usr/x86_64-w64-mingw32

make -j6

sudo checkinstall --pkgname=zlib-mingw-w64-x86-64 \
--pkgversion="1:1.2.7.$(date +%Y%m%d)-0ubuntu1" \
--backup=no --deldoc=yes --fstrans=no --default

bzip2

まず、このパッチを当ててから以下の作業を行う。
make libbz2.a
sudo install -m 644 bzlib.h /usr/x86_64-w64-mingw32/include
sudo install -m 644 libbz2.a /usr/x86_64-w64-mingw32/lib

XZ Utils

CFLAGS="-pipe -O2" \
CXXFLAGS="${CFLAGS}" \
PKG_CONFIG_PATH=/usr/x86_64-w64-mingw32/lib/pkgconfig \
./configure --prefix=/usr/x86_64-w64-mingw32 \
--host=x86_64-w64-mingw32 \
--disable-shared

make -j6

sudo checkinstall --pkgname=xz-utils-mingw-w64-x86-64 \
--pkgversion="1:5.0.4.$(date +%Y%m%d)-0ubuntu1" \
--backup=no --deldoc=yes --fstrans=no --default

SDL

gpac の依存ライブラリ
CFLAGS="-pipe -O2" \
CXXFLAGS="${CFLAGS}" \
PKG_CONFIG_PATH=/usr/x86_64-w64-mingw32/lib/pkgconfig \
./configure --prefix=/usr/x86_64-w64-mingw32 \
--host=x86_64-w64-mingw32 \
--disable-shared

make -j6

sudo checkinstall --pkgname=libsdl-mingw-w64-x86-64 \
--pkgversion="1:1.2.15.$(date +%Y%m%d)-0ubuntu1" \
--backup=no --deldoc=yes --fstrans=no --default

gpac

本家ソースの最新版をコンパイルしてみた。
gpac の依存ライブラリ。
そのままで、Ubuntu 上の MinGW 環境で、静的ライブラリをクロスコンパイルしようとしたら、ひどい有様だった。仕方がないのでパッチを当てたら、パッチファイルが 1300 行を超えた・・・・
パッチは、MinGW 環境での、静的ライブラリ生成専用。動的ライブラリの生成は、できないので注意。
はじめに上記のパッチを当ててから作業を開始する。
パッケージの情報が記述されているが、余計なお世話なのでリネーム
mv gpac.spec gpac.spec_org

PKG_CONFIG_PATH=/usr/x86_64-w64-mingw32/lib/pkgconfig \
./configure  --prefix=/usr/x86_64-w64-mingw32 \
--cross-prefix=x86_64-w64-mingw32- --cpu=x86_64 \
--extra-cflags="-pipe"

make -j6

sudo checkinstall --pkgname=libgpac-mingw-w64-x86-64 \
--pkgversion="1:0.5.0.$(date +%Y%m%d)-0ubuntu1" \
--backup=no --deldoc=yes --fstrans=no --default \
sudo make install install-lib


ビルド(1週目)

ffmpeg

各ライブラリは、相互依存するので、はじめは最小構成で FFmpeg をビルドする。
git clone git://source.ffmpeg.org/ffmpeg.git ffmpeg
commit 83438a0db3c61f06979d1c4159e5c85d52eda488
Date:   Mon Sep 17 00:40:55 2012 +0200
2週目のためにこのパッチを当てる。1週目では必要ないが、ここで当てておく。
PKG_CONFIG_PATH=/usr/x86_64-w64-mingw32/lib/pkgconfig \
./configure --prefix=/usr/x86_64-w64-mingw32 --enable-gpl \
--enable-version3 --enable-nonfree \
--enable-postproc --enable-memalign-hack \
--enable-runtime-cpudetect --enable-avisynth \
--enable-w32threads --cross-prefix=x86_64-w64-mingw32- \
--target-os=mingw32 --arch=x86_64 --cpu=x86_64 \
--extra-cflags="-pipe" --extra-cxxflags="-pipe"

make -j6

sudo checkinstall --pkgname=ffmpeg-mingw-w64-x86-64 \
--pkgversion="1:20120909.$(date +%Y%m%d)-0ubuntu1" \
--backup=no --deldoc=yes --fstrans=no --default

ffms2

svn checkout http://ffmpegsource.googlecode.com/svn/trunk/ ffms2
リビジョン: 712

CFLAGS="-pipe -O2" \
CXXFLAGS="${CFLAGS}" \
PKG_CONFIG_PATH=/usr/x86_64-w64-mingw32/lib/pkgconfig \
./configure --prefix=/usr/x86_64-w64-mingw32 --host=x86_64-w64-mingw32 \
--disable-silent-rules --enable-dependency-tracking \
--disable-shared --enable-static

make -j6

sudo checkinstall --pkgname=ffms2-mingw-w64-x86-64 \
--pkgversion="1:712.$(date +%Y%m%d)-0ubuntu1" \
--backup=no --deldoc=yes --fstrans=no --default \
make install-strip

x264

git clone git://git.videolan.org/x264.git x264
commit 198a7ea13ccb727d4ea24b29f5da9b0292387309
Date:   Thu Aug 16 13:40:32 2012 -0700
まず、このパッチを当ててから以下の作業を行う。
CFLAGS="-pipe -O2" \
CXXFLAGS="${CFLAGS}" \
PKG_CONFIG_PATH=/usr/x86_64-w64-mingw32/lib/pkgconfig \
./configure --prefix=/usr/x86_64-w64-mingw32 \
--host=x86_64-w64-mingw32 \
--cross-prefix=x86_64-w64-mingw32- \
--enable-win32thread \
--enable-static \
--extra-cflags="-pipe -O2" \
--extra-ldflags="-lws2_32"


platform:      X86_64
system:        WINDOWS
cli:           yes
libx264:       internal
shared:        no
static:        yes
asm:           yes
interlaced:    yes
avs:           yes
lavf:          yes
ffms:          yes
gpac:          yes
gpl:           yes
thread:        win32
filters:       resize crop select_every 
debug:         no
gprof:         no
strip:         no
PIC:           no
visualize:     no
bit depth:     8
chroma format: all


make -j6

sudo checkinstall --pkgname=libx264-mingw-w64-x86-64 \
--pkgversion="1:20120816.$(date +%Y%m%d)-0ubuntu1" \
--backup=no --deldoc=yes --fstrans=no --default


依存ライブラリのビルド(2週目)

OpenSSL

make に 並列ビルドオプション(-j)をつけると、undefined エラーとなる。
PKG_CONFIG_PATH=/usr/x86_64-w64-mingw32/lib/pkgconfig \
./Configure --prefix=/usr/x86_64-w64-mingw32 \
--cross-compile-prefix=x86_64-w64-mingw32- \
mingw64 threads zlib no-shared

make

sudo checkinstall --pkgname=openssl-mingw-w64-x86-64 \
--pkgversion="1:1.0.1c.$(date +%Y%m%d)-0ubuntu1" \
--backup=no --deldoc=yes --fstrans=no --default

libpng

openjpeg の依存ライブラリ
CFLAGS="-pipe -O2" \
CXXFLAGS="${CFLAGS}" \
PKG_CONFIG_PATH=/usr/x86_64-w64-mingw32/lib/pkgconfig \
./configure --prefix=/usr/x86_64-w64-mingw32 \
--host=x86_64-w64-mingw32 \
--disable-shared

make -j6

sudo checkinstall --pkgname=libpng-mingw-w64-x86-64 \
--pkgversion="1:1.5.12.$(date +%Y%m%d)-0ubuntu1" \
--backup=no --deldoc=yes --fstrans=no --default

libtiff

openjpeg の依存ライブラリ
4.0.2 でやってみたら、openjpeg で認識してくれなかったので、3.9.6 にした。
CFLAGS="-pipe -O2" \
CXXFLAGS="${CFLAGS}" \
PKG_CONFIG_PATH=/usr/x86_64-w64-mingw32/lib/pkgconfig \
./configure --prefix=/usr/x86_64-w64-mingw32 \
--host=x86_64-w64-mingw32 \
--disable-shared

make -j6

sudo checkinstall --pkgname=libtiff-mingw-w64-x86-64 \
--pkgversion="1:3.9.6.$(date +%Y%m%d)-0ubuntu1" \
--backup=no --deldoc=yes --fstrans=no --default

libjpeg-turbo

openjpeg の依存ライブラリ
CFLAGS="-pipe -O2" \
CXXFLAGS="${CFLAGS}" \
PKG_CONFIG_PATH=/usr/x86_64-w64-mingw32/lib/pkgconfig \
./configure --prefix=/usr/x86_64-w64-mingw32 \
--host=x86_64-w64-mingw32 \
--disable-shared

make -j6

sudo checkinstall --pkgname=libjpeg-turbo-mingw-w64-x86-64 \
--pkgversion="1:1.2.1.$(date +%Y%m%d)-0ubuntu1" \
--backup=no --deldoc=yes --fstrans=no --default

lcms2

openjpeg の依存ライブラリ
CFLAGS="-pipe -O2" \
CXXFLAGS="${CFLAGS}" \
PKG_CONFIG_PATH=/usr/x86_64-w64-mingw32/lib/pkgconfig \
./configure --prefix=/usr/x86_64-w64-mingw32 \
--host=x86_64-w64-mingw32 \
--disable-shared

make -j6

sudo checkinstall --pkgname=liblcms2-mingw-w64-x86-64 \
--pkgversion="1:2.3.$(date +%Y%m%d)-0ubuntu1" \
--backup=no --deldoc=yes --fstrans=no --default

lame

CFLAGS="-pipe -O2" \
CXXFLAGS="${CFLAGS}" \
PKG_CONFIG_PATH=/usr/x86_64-w64-mingw32/lib/pkgconfig \
./configure --prefix=/usr/x86_64-w64-mingw32 \
--host=x86_64-w64-mingw32 \
--disable-shared \
--enable-nasm

make -j6

sudo checkinstall --pkgname=lame-mingw-w64-x86-64 \
--pkgversion="1:3.99.5.$(date +%Y%m%d)-0ubuntu1" \
--backup=no --deldoc=yes --fstrans=no --default

faac

CFLAGS="-pipe -O2" \
CXXFLAGS="${CFLAGS}" \
PKG_CONFIG_PATH=/usr/x86_64-w64-mingw32/lib/pkgconfig \
./configure --prefix=/usr/x86_64-w64-mingw32 \
--host=x86_64-w64-mingw32 --disable-shared --without-mp4v2

make -j6

sudo checkinstall --pkgname=faac-mingw-w64-x86-64 \
--pkgversion="1:1.28.$(date +%Y%m%d)-0ubuntu1" \
--backup=no --deldoc=yes --fstrans=no --default

libogg

CFLAGS="-pipe -O2" \
CXXFLAGS="${CFLAGS}" \
PKG_CONFIG_PATH=/usr/x86_64-w64-mingw32/lib/pkgconfig \
./configure --prefix=/usr/x86_64-w64-mingw32 \
--host=x86_64-w64-mingw32 --disable-shared

make -j6

sudo checkinstall --pkgname=libogg-mingw-w64-x86-64 \
--pkgversion="1:1.3.0.$(date +%Y%m%d)-0ubuntu1" \
--backup=no --deldoc=yes --fstrans=no --default

libvorbis

CFLAGS="-pipe -O2" \
CXXFLAGS="${CFLAGS}" \
PKG_CONFIG_PATH=/usr/x86_64-w64-mingw32/lib/pkgconfig \
./configure --prefix=/usr/x86_64-w64-mingw32 \
--host=x86_64-w64-mingw32 --disable-shared

make -j6

sudo checkinstall --pkgname=libvorbis-mingw-w64-x86-64 \
--pkgversion="1:1.3.3.$(date +%Y%m%d)-0ubuntu1" \
--backup=no --deldoc=yes --fstrans=no --default

libtheora

CFLAGS="-pipe -O2" \
CXXFLAGS="${CFLAGS}" \
PKG_CONFIG_PATH=/usr/x86_64-w64-mingw32/lib/pkgconfig \
./configure --prefix=/usr/x86_64-w64-mingw32 \
--host=x86_64-w64-mingw32 --disable-shared

make -j6

sudo checkinstall --pkgname=libtheora-mingw-w64-x86-64 \
--pkgversion="1:1.1.1.$(date +%Y%m%d)-0ubuntu1" \
--backup=no --deldoc=yes --fstrans=no --default

libspeex

CFLAGS="-pipe -O2" \
CXXFLAGS="${CFLAGS}" \
PKG_CONFIG_PATH=/usr/x86_64-w64-mingw32/lib/pkgconfig \
./configure --prefix=/usr/x86_64-w64-mingw32 \
--host=x86_64-w64-mingw32 --disable-shared --enable-sse

make -j6

sudo checkinstall --pkgname=libspeex-mingw-w64-x86-64 \
--pkgversion="1:1.2rc1.$(date +%Y%m%d)-0ubuntu1" \
--backup=no --deldoc=yes --fstrans=no --default

opencore-amr

CFLAGS="-pipe -O2" \
CXXFLAGS="${CFLAGS}" \
PKG_CONFIG_PATH=/usr/x86_64-w64-mingw32/lib/pkgconfig \
./configure --prefix=/usr/x86_64-w64-mingw32 \
--host=x86_64-w64-mingw32 --disable-shared

make -j6

sudo checkinstall --pkgname=libopencore-amr-mingw-w64-x86-64 \
--pkgversion="1:0.1.2.$(date +%Y%m%d)-0ubuntu1" \
--backup=no --deldoc=yes --fstrans=no --default

openjpeg

make -j6 だと、エラーとなる。早すぎたんだ・・・
CFLAGS="-pipe -O2" \
CXXFLAGS="${CFLAGS}" \
PKG_CONFIG_PATH=/usr/x86_64-w64-mingw32/lib/pkgconfig \
LIBS="-lpng" \
./configure --prefix=/usr/x86_64-w64-mingw32 \
--host=x86_64-w64-mingw32 --disable-shared

----------------------------------------------
           your configuration

--with-png-libraries: yes
libpng header       : yes
--enable-tiff       : yes
libtiff header      : yes
--enable-lcms2      : yes
lcms2 header        : yes
lcms2 version       : 2.3
--enable-lcms1      : no
lcms1 header        : no
lcms1 version       : 
--enable-jpwl       : no
--enable-jp3d       : no
--enable-shared     : no
----------------------------------------------

make

sudo checkinstall --pkgname=libopenjpeg-mingw-w64-x86-64 \
--pkgversion="1:1.4.r697.$(date +%Y%m%d)-0ubuntu1" \
--backup=no --deldoc=yes --fstrans=no --default

xvidcore

以下のようなエラーとなるので

GCC4 から、無くなったオプション
  C: ./decoder.c
cc1: エラー: 認識できないコマンドラインオプション ‘-mno-cygwin’ です

原因は、-DWINDOWS オプション。
以下のコマンドで、生成されたオブジェクトファイルの中身をのぞくと、関数名の先頭にアンダースコアが付いている。
x86_64-w64-mingw32-nm build/generic/\=build/utils/x86_asm/cpuid.obj
  L: xvidcore.a
  L: xvidcore.dll
Creating library file: xvidcore.dll.a
xvid.obj:xvid.c:(.text+0xe0): undefined reference to `check_cpu_features'
xvid.obj:xvid.c:(.text+0x65c): undefined reference to `emms_mmx'
xvid.obj:xvid.c:(.text+0x673): undefined reference to `fdct_mmx_skal'
xvid.obj:xvid.c:(.text+0x67a): undefined reference to `idct_mmx'
...
plugins/plugin_ssim.obj:plugin_ssim.c:(.text+0x12c1): undefined reference to `check_cpu_features'
plugins/plugin_ssim.obj:plugin_ssim.c:(.text+0x12d8): undefined reference to `lum_8x8_mmx'
plugins/plugin_ssim.obj:plugin_ssim.c:(.text+0x12e3): undefined reference to `consim_mmx'
plugins/plugin_ssim.obj:plugin_ssim.c:(.text+0x12fb): undefined reference to `consim_sse2'
collect2: ld はステータス 1 で終了しました
make: *** [xvidcore.dll] エラー 1

まず、このパッチを当ててから以下の作業を行う。

CFLAGS="-pipe -O2" \
CXXFLAGS="${CFLAGS}" \
PKG_CONFIG_PATH=/usr/x86_64-w64-mingw32/lib/pkgconfig \
AFLAGS="-DNO_PREFIX" \
./configure --prefix=/usr/x86_64-w64-mingw32 \
--host=x86_64-w64-mingw32

make -j6

sudo checkinstall --pkgname=libxvidcore-mingw-w64-x86-64 \
--pkgversion="1:1.3.2.$(date +%Y%m%d)-0ubuntu1" \
--backup=no --deldoc=yes --fstrans=no --default

gsm

まず、このパッチを当ててから以下の作業を行う。

make -j6

sudo checkinstall --pkgname=libgsm-mingw-w64-x86-64 \
--pkgversion="1:1.0.13.$(date +%Y%m%d)-0ubuntu1" \
--backup=no --deldoc=yes --fstrans=no --default \
make gsminstall

rtmpdump

git clone git://git.ffmpeg.org/rtmpdump
commit e0056c51cc1710c9a44d2a2c4e2f344fa9cabcf4
Date:   Tue Jul 24 17:17:26 2012 +0200

make SYS=mingw SHARED= CROSS_COMPILE=x86_64-w64-mingw32- \
OPT="-O2" XLIBS="-lcrypt32" \
prefix=/usr/x86_64-w64-mingw32

sudo checkinstall --pkgname=rtmpdump-mingw-w64-x86-64 \
--pkgversion="1:$(date +%Y%m%d)-0ubuntu1" \
--backup=no --deldoc=yes --fstrans=no --default \
make SYS=mingw SHARED= CROSS_COMPILE=x86_64-w64-mingw32- \
OPT="-O2" XLIBS="-lcrypt32" \
install prefix=/usr/x86_64-w64-mingw32

libvpx

pthread がインストールされていない場合、win32thread を利用するようになる。 その時に、windows.h が import されずに「不明な型名 CRITICAL_SECTION」エラーとなるため、このパッチを当てる。
CFLAGS="-pipe -O2" \
CXXFLAGS="${CFLAGS}" \
PKG_CONFIG_PATH=/usr/x86_64-w64-mingw32/lib/pkgconfig \
CROSS=x86_64-w64-mingw32- \
./configure --target=x86_64-win64-gcc --prefix=/usr/x86_64-w64-mingw32 \
--disable-shared \
--disable-examples

make -j6

sudo checkinstall --pkgname=libvpx-mingw-w64-x86-64 \
--pkgversion="1:1.1.0.$(date +%Y%m%d)-0ubuntu1" \
--backup=no --deldoc=yes --fstrans=no --default

libfdk-aac

今回は、GitHub からソースを取得した。
git clone https://github.com/mstorsjo/fdk-aac.git
cd fdk-aac

fdk-aac$ git log
commit 226601a8d9bce81455e161a0e26051d2f22c5d7a
Date:   Mon Mar 18 16:23:17 2013 +0200

CFLAGS="-pipe -O2" \
CXXFLAGS="${CFLAGS}" \
PKG_CONFIG_PATH=/usr/x86_64-w64-mingw32/lib/pkgconfig \
./configure --prefix=/usr/x86_64-w64-mingw32 \
--host=x86_64-w64-mingw32 \
--disable-shared --enable-static --enable-fast-install

make -j6

sudo checkinstall --pkgname=libfdk-aac-mingw-w64-x86-64 \
--pkgversion="1:0.1.1.$(date +%Y%m%d)-0ubuntu1" \
--backup=no --deldoc=yes --fstrans=no --default

ビルド(2週目)

ffmpeg

make clean

PKG_CONFIG_PATH=/usr/x86_64-w64-mingw32/lib/pkgconfig \
./configure --prefix=/usr/x86_64-w64-mingw32 \
--cross-prefix=x86_64-w64-mingw32- --target-os=mingw32 \
--arch=x86_64 --cpu=x86_64 --enable-gpl --enable-version3 \
--enable-nonfree --enable-postproc \
--enable-memalign-hack --enable-runtime-cpudetect \
--enable-avisynth --disable-debug \
--extra-libs="-lws2_32 -lgdi32 -lwinmm"  --enable-w32threads \
--enable-zlib --enable-bzlib --enable-libmp3lame \
--enable-libfaac --enable-libvorbis --enable-libtheora \
--enable-libspeex --enable-libopencore-amrnb \
--enable-libopencore-amrwb --enable-libopenjpeg \
--enable-libxvid --enable-libgsm \
--enable-librtmp \
--enable-libx264 \
--enable-libfdk-aac \
--extra-cflags="-pipe" --extra-cxxflags="-pipe"

make -j6

sudo checkinstall --pkgname=ffmpeg-mingw-w64-x86-64 \
--pkgversion="1:20120909.$(date +%Y%m%d)-0ubuntu1" \
--backup=no --deldoc=yes --fstrans=no --default

ffms2

make clean

CFLAGS="-pipe -O2" \
CXXFLAGS="${CFLAGS}" \
PKG_CONFIG_PATH=/usr/x86_64-w64-mingw32/lib/pkgconfig \
./configure --prefix=/usr/x86_64-w64-mingw32 --host=x86_64-w64-mingw32

make -j6

sudo checkinstall --pkgname=ffms2-mingw-w64-x86-64 \
--pkgversion="1:712.$(date +%Y%m%d)-0ubuntu1" \
--backup=no --deldoc=yes --fstrans=no --default \
make install-strip

x264

configure で、ライブラリを指定しまくらないと、ffms2 が有効にならない。自動的に設定してくれないものなのか・・・
config.log を頼りに、不足のライブラリをせっせと追加したが、心が折れそうになった。
make clean

PKG_CONFIG_PATH=/usr/x86_64-w64-mingw32/lib/pkgconfig \
./configure --prefix=/usr/x86_64-w64-mingw32 \
--host=x86_64-w64-mingw32 \
--cross-prefix=x86_64-w64-mingw32- \
--enable-win32thread --enable-static --enable-strip \
--extra-cflags="-pipe -O2" \
--extra-ldflags="-lx264 -lfdk-aac -lfaac -lgsm -lmp3lame -lopencore-amrnb -lopencore-amrwb -lopenjpeg -ltheoraenc -ltheoradec -lspeex -lvorbis -lvorbisenc -logg -lxvidcore -lrtmp -lssl -lcrypto -lws2_32 -lgdi32 -lwinmm"

make -j6

sudo checkinstall --pkgname=libx264-mingw-w64-x86-64 \
--pkgversion="1:20120816.$(date +%Y%m%d)-0ubuntu1" \
--backup=no --deldoc=yes --fstrans=no --default


実行ファイルのチェック

ビルドした実行ファイルが、DLL 依存になっていないかをチェック。
$ x86_64-w64-mingw32-objdump -p x264.exe | grep 'DLL Name'
 DLL Name: ADVAPI32.dll
 DLL Name: AVIFIL32.dll
 DLL Name: GDI32.dll
 DLL Name: KERNEL32.dll
 DLL Name: msvcrt.dll
 DLL Name: msvcrt.dll
 DLL Name: USER32.dll
 DLL Name: WINMM.dll
 DLL Name: WS2_32.dll

$ x86_64-w64-mingw32-objdump -p ffmpeg.exe | grep 'DLL Name'
 DLL Name: ADVAPI32.dll
 DLL Name: AVICAP32.dll
 DLL Name: AVIFIL32.dll
 DLL Name: GDI32.dll
 DLL Name: KERNEL32.dll
 DLL Name: msvcrt.dll
 DLL Name: msvcrt.dll
 DLL Name: PSAPI.DLL
 DLL Name: SHELL32.dll
 DLL Name: USER32.dll
 DLL Name: WINMM.dll
 DLL Name: WS2_32.dll


備忘録

ビルド中に発生した問題の解決方法を備忘録として残しておく。

configure の先頭行のシェルに -x オプションを付け、デバッグ出力する。

configu.log をみて、依存ライブラリチェック処理のエラーなどを確認する。

undefined reference が、発生した場合は、/usr/x86_64-w64-mingw32 ディレクトリで、
fgrep -r --exclude-dir="bin" --exclude-dir="sbin" 未定義ラベル名 *
のようにして、探す。
ライブラリが絞り込めたら、
x86_64-w64-mingw32-nm lib/libtheoraenc.a | grep th_encode_flushheader
のようにすると、
U th_encode_flushheader
0000000000004d70 T th_encode_flushheader
のように表示される。U は未定義、T などになっているものを探す。


2012年9月9日日曜日

Ubuntu 上に、Windows 64bit 用のクロスコンパイル環境を構築

はじめに

Ubuntu 上に、Windows 64bit 用のクロスコンパイル環境を構築したくなった。
Windows 7 に VMware をインストールし、その上で Ubuntu を動作させることとする。

動作環境

Windows 7 Professional 64bit SP1
VMware Playre 5 (VMware-player-5.0.0-812388.exe)
Ubuntu 12.04 LTS Alternative amd64 (ubuntu-12.04.1-alternate-amd64.iso)

環境構築

VMware は、インストール済みとする。

仮想マシンの作成

VMware を起動し、「新規仮想マシンの作成」を行う。
以下、設定した値を列挙する。
インストール元:「後で OS をインストール」を選択。
※ 「インストーラ ディスク イメージ ファイル」を選択すると、「簡易インストール」モードになってしまい、デスクトップ環境がインストールされない。通常インストールするには、「後で OS をインストール」を選択する必要がある。

ゲストOS:「Linux」
バージョン:「Ubuntu 64ビット」
仮想マシン名:「Ubuntu64」
場所:任意
ディスク最大サイズ(GB):「50」
「仮想ディスクを単一ファイルとして格納」

「ハードウェアをカスタマイズ」ボタンを押下。
メモリ:「2048」MB
プロセッサ:「4」
新規 CD/DVD(IDE):接続「ISO イメージ ファイルを使用する」、「ubuntu-12.04.1-alternate-amd64.iso」を指定する。

Ubuntu のインストール

仮想マシンを起動すると、Ubuntu のインストールが始まる。
適宜、値を設定する。
インストール中、ウィンドウ下部に、VMware Tools のインストールを促すメッセージが出るが、インストール完了まで放置しておく。

ディスクのパーティショニングについは、「ガイド - ディスク全体を使い、LVM をセットアップする」を選択した。この項目は、Alternate 版のみで表示される項目(なはず)。

ポコペンッ と Ubuntu が起動したら、インストール中に設定した、ユーザーでログインする。

アップデート

端末を起動
※ 10.04 を使っていたので、12.04 では UI 周りがガラッと変わっていて、よ~わからん状態・・・。最初は、端末の起動をするだけで、悶絶してしまったw。
左上の「Dash ホーム」をクリックして、「端末」と入力して検索するか、「Dash ホーム」アイコンを右クリックして、「アプリケーション」を選択、「インストール済み」の中から、探し出す。
む~・・・慣れの問題か・・・。

sudo aptitude update
sudo aptitude full-upgrade

VMware Tools のインストール

ウィンドウ下に、ずっと出ていた「ツールのインストール」ボタンを押下。
ドライブがマウントされ、「VMwareTools-9.2.0-799703.tar.gz」ファイルが表示される。
ファイルを右クリックして、「展開...」を選択。
展開先を適宜選択して、「展開」ボタンを押下。

「端末」のコマンドラインで、展開先の「vmware-tools-distrib」ディレクトリに移動。
sudo ./vmware-install.pl

すべてデフォルト値のまま Enter

再起動する。
sudo reboot now

MinGW-w64 をインストール

端末を起動

sudo aptitude install mingw-w64 g++-mingw-w64 binutils-mingw-w64

以下の新規パッケージがインストールされます:
  binutils-mingw-w64 binutils-mingw-w64-i686{a} binutils-mingw-w64-x86-64{a} g++-4.6{a} g++-mingw-w64 g++-mingw-w64-i686{a} 
  g++-mingw-w64-x86-64{a} gcc-mingw-w64{a} gcc-mingw-w64-base{a} gcc-mingw-w64-i686{a} gcc-mingw-w64-x86-64{a} libstdc++6-4.6-dev{a} 
  mingw-w64 mingw-w64-dev{a} 
0 個のパッケージを更新、 14 個を新たにインストール、 0 個を削除予定、0 個が更新されていない。
80.5 M バイトのアーカイブを取得する必要があります。 展開後に 341 M バイトのディスク領域が新たに消費されます。
先に進みますか? [Y/n/?] 

インストールが完了すると、「/usr/bin」に「x86_64-w64-mingw32-c++」などのコマンドが増えている。
「/usr/x86_64-w64-mingw32」にクロスコンパイル用のヘッダや、ライブラリが格納されている。

インストールしたバージョン

binutils-mingw-w64          2.22-2ubuntu1+1
binutils-mingw-w64-i686     2.22-2ubuntu1+1
binutils-mingw-w64-x86-64   2.22-2ubuntu1+1
g++-mingw-w64               4.6.3-1ubuntu5+5ubuntu1
g++-mingw-w64-i686          4.6.3-1ubuntu5+5ubuntu1
g++-mingw-w64-x86-64        4.6.3-1ubuntu5+5ubuntu1
gcc-mingw-w64               4.6.3-1ubuntu5+5ubuntu1
gcc-mingw-w64-base          4.6.3-1ubuntu5+5ubuntu1
gcc-mingw-w64-i686          4.6.3-1ubuntu5+5ubuntu1
gcc-mingw-w64-x86-64        4.6.3-1ubuntu5+5ubuntu1
mingw-w64                   2.0.1-1
mingw-w64-dev               2.0.1-1


その他ツールのインストール

nasm および yasm

両方ともアセンブラ。ビルド時に必要になることがある。両方入れておけば、問題ない。

sudo aptitude install nasm yasm

構成管理ツール

git および subversion をインストール。

sudo aptitude install git subversion

checkinstall

make install などで、インストールすると、パッケージ管理の対象外となってしまうが、checkinstall を使用することで、rpm や dep などのパッケージを作成でき、パッケージ管理可能となる。

sudo aptitude install checkinstall

autoreconf

autogen.sh の中で使ってたりする。

sudo aptitude install dh-autoreconf

ccache

コンパイル結果をキャッシュして、2回目以降の実行時間を短縮するためのツール。1回しかコンパイルしないのならば、必要ない。

sudo aptitude install ccache

ccache g++ hoge.cpp のように実行する方法や、 PATH の先頭に /usr/lib/ccache/ ディレクトリを追加して、 g++ などのリンクファイル(リンク先は、ccache)を実行する方法などがある。
/usr/lib/ccache/ ディレクトリの実行リンクファイルは、ccache のインストール時に、自動的に更新されるようだ。

実際には以下のようにする。
PATH=/usr/lib/ccache:${PATH} make

実行結果のキャッシュ先は、デフォルトで「${HOME}/.ccache」ディレクトリになっている。
変更する場合は、「CCACHE_DIR」環境変数に設定する。

最大キャッシュサイズのデフォルト値は、1GBになっている。必要に応じて、最大値を以下のように設定できる。10 GByte に増やした。設定は、キャッシュディレクトリごとに、行う必要がある。

CCACHE_DIR=${HOME}/.ccache-mingw64 \
ccache -M 10G

設定した値は、以下のように確認できる。

CCACHE_DIR=${HOME}/.ccache-mingw64 \
ccache -s

cache directory                     /home/user1/.ccache-mingw64
cache hit (direct)                    34
cache hit (preprocessed)               0
cache miss                            42
called for link                       18
preprocessor error                     1
no input file                          1
files in cache                        99
cache size                           564 Kbytes
max cache size                      10.0 Gbytes

「CCACHE_DIR」は、デフォルト値のディレクトリを利用する場合、いちいち指定する必要はない。または、export しておいてもよい。

ビルド

実際にビルドを行ってみる。

zlib

zlib のページからソース(zlib-1.2.7.tar.bz2)をダウンロードしてくる。
適当なディレクトリでソースを展開。

tar jxvf zlib-1.2.7.tar.bz2
cd zlib-1.2.7

CC=x86_64-w64-mingw32-gcc \
AR=x86_64-w64-mingw32-ar \
RANLIB=x86_64-w64-mingw32-ranlib \
LDSHAREDLIBC="" \
./configure --prefix=/usr/x86_64-w64-mingw32

PATH=/usr/lib/ccache:${PATH} \
CCACHE_DIR=${HOME}/.ccache-mingw64 \
make

sudo checkinstall --pkgname=zlib-mingw-w64-x86-64 \
--pkgversion="1:1.2.7.$(date +%Y%m%d)-0ubuntu1" \
--backup=no --deldoc=yes --fstrans=no --default

完了

アンインストールする場合は、「dpkg -r zlib-mingw-w64-x86-64」とする。






2012年8月18日土曜日

Android NDK で ffmpeg ライブラリをビルド

とりあえず、手順だけメモ。
色々納得できないので、要継続調査。

  • NEON 有効
  • スタティックライブラリ生成
  • ダイナミックライブラリ生成
  • x264 ライブラリを利用

git clone git://source.ffmpeg.org/ffmpeg.git ffmpeg

commit 7e49474aa02e93ba2d80b330cba1ec38f4c4f3ee
Date:   Sat Aug 18 05:02:58 2012 +0200

configure を修正

$ git diff configure
diff --git a/configure b/configure
index 679fae0..1591f4f 100755
--- a/configure
+++ b/configure
@@ -1949,7 +1949,7 @@ cc_default="gcc"
 cxx_default="g++"
 host_cc_default="gcc"
 install="install"
-ln_s="ln -sf"
+ln_s="cp -f"
 nm_default="nm"
 objformat="elf"
 pkg_config_default=pkg-config
@@ -3956,7 +3956,7 @@ YASM=$yasmexe
 DEPYASM=$yasmexe
 AR=$ar
 RANLIB=$ranlib
-CP=cp -p
+CP=cp -fp
 LN_S=$ln_s
 STRIP=$strip
 CPPFLAGS=$CPPFLAGS

configure 実行

TEMPDIR=`cygpath -m /tmp` \
./configure \
--sysroot=`cygpath -m $SYSROOT` \
--cross-prefix=arm-linux-androideabi- \
--enable-cross-compile \
--target-os=linux \
--arch=arm \
--cpu=cortex-a8 \
--extra-cflags='-I../x264 -mfloat-abi=softfp -mfpu=neon' \
--extra-ldflags='-L../x264 -Wl,--fix-cortex-a8' \
--enable-libx264 \
--enable-shared \
--disable-stripping \
--enable-gpl \
--enable-version3 \
--disable-doc \
--disable-htmlpages \
--disable-manpages \
--disable-podpages \
--disable-txtpages \
--disable-ffmpeg \
--disable-ffplay \
--disable-ffprobe \
--disable-ffserver \
--disable-avdevice \
--disable-network \
--disable-devices \
--disable-protocols \
--enable-protocol=file

config.h を修正

#define CC_IDENT "gcc 4.4.3^M (GCC)"
↓
#define CC_IDENT "gcc 4.4.3 (GCC)"

config.mak を修正

CC_IDENT=gcc 4.4.3^M (GCC)
↓
CC_IDENT=gcc 4.4.3 (GCC)

ビルド実行

make -j4
「-j4」は、並列ビルドオプション。

インストール

install -m 644 libavfilter/libavfilter.a "/usr/local/lib"
install -m 755 libavfilter/libavfilter.so "/usr/local/lib/libavfilter.so.3.10.100"

install -m 644 libavformat/libavformat.a "/usr/local/lib"
install -m 755 libavformat/libavformat.so "/usr/local/lib/libavformat.so.54.25.100"

install -m 644 libavcodec/libavcodec.a "/usr/local/lib"
install -m 755 libavcodec/libavcodec.so "/usr/local/lib/libavcodec.so.54.53.100"

install -m 644 libpostproc/libpostproc.a "/usr/local/lib"
install -m 755 libpostproc/libpostproc.so "/usr/local/lib/libpostproc.so.52.0.100"

install -m 644 libswresample/libswresample.a "/usr/local/lib"
install -m 755 libswresample/libswresample.so "/usr/local/lib/libswresample.so.0.15.100"

install -m 644 libswscale/libswscale.a "/usr/local/lib"
install -m 755 libswscale/libswscale.so "/usr/local/lib/libswscale.so.2.1.101"

install -m 644 libavutil/libavutil.a "/usr/local/lib"
install -m 755 libavutil/libavutil.so "/usr/local/lib/libavutil.so.51.70.100"

install -m 644 libavfilter/asrc_abuffer.h libavfilter/avcodec.h libavfilter/avfilter.h libavfilter/avfiltergraph.h libavfilter/buffersink.h libavfilter/buffersrc.h libavfilter/version.h "/usr/local/include/libavfilter"
install -m 644 libavfilter/libavfilter.pc "/usr/local/lib/pkgconfig"

install -m 644 libavformat/avformat.h libavformat/avio.h libavformat/version.h "/usr/local/include/libavformat"
install -m 644 libavformat/libavformat.pc "/usr/local/lib/pkgconfig"

install -m 644 libavcodec/avcodec.h libavcodec/avfft.h libavcodec/dxva2.h libavcodec/old_codec_ids.h libavcodec/vaapi.h libavcodec/vda.h libavcodec/vdpau.h libavcodec/version.h libavcodec/xvmc.h "/usr/local/include/libavcodec"
install -m 644 libavcodec/libavcodec.pc "/usr/local/lib/pkgconfig"

install -m 644 libpostproc/postprocess.h "/usr/local/include/libpostproc"
install -m 644 libpostproc/libpostproc.pc "/usr/local/lib/pkgconfig"

install -m 644 libswresample/swresample.h "/usr/local/include/libswresample"
install -m 644 libswresample/libswresample.pc "/usr/local/lib/pkgconfig"

install -m 644 libswscale/swscale.h libswscale/version.h "/usr/local/include/libswscale"
install -m 644 libswscale/libswscale.pc "/usr/local/lib/pkgconfig"

install -m 644 libavutil/adler32.h libavutil/aes.h libavutil/attributes.h libavutil/audio_fifo.h libavutil/audioconvert.h libavutil/avassert.h libavutil/avstring.h libavutil/avutil.h libavutil/base64.h libavutil/blowfish.h libavutil/bprint.h libavutil/bswap.h libavutil/common.h libavutil/cpu.h libavutil/crc.h libavutil/error.h libavutil/eval.h libavutil/fifo.h libavutil/file.h libavutil/imgutils.h libavutil/intfloat.h libavutil/intfloat_readwrite.h libavutil/intreadwrite.h libavutil/lfg.h libavutil/log.h libavutil/lzo.h libavutil/mathematics.h libavutil/md5.h libavutil/mem.h libavutil/dict.h libavutil/opt.h libavutil/parseutils.h libavutil/pixdesc.h libavutil/pixfmt.h libavutil/random_seed.h libavutil/rational.h libavutil/samplefmt.h libavutil/sha.h libavutil/time.h libavutil/timecode.h libavutil/timestamp.h libavutil/version.h libavutil/xtea.h libavutil/avconfig.h "/usr/local/include/libavutil"
install -m 644 libavutil/libavutil.pc "/usr/local/lib/pkgconfig"

Android NDK で x264 ライブラリをビルド

git clone git://git.videolan.org/x264.git
cd x264
CFLAGS='-march=armv7-a -mtune=cortex-a8 -mfloat-abi=softfp -mfpu=neon' \
LDFLAGS='-Wl,--fix-cortex-a8' \
./configure --disable-cli --enable-shared --enable-static --host=arm-linux-androideabi --cross-prefix=arm-linux-androideabi-
make -j4
NEON を利用する。(-mfpu=neon)
実行ファイルは、生成しない。(--disable-cli)
ダイナミックリンクライブラリを生成。(--enable-shared)
スタティックリンクライブラリを生成。(--enable-static)
並列ビルド(-j4)

ビルドしたバージョン
commit 5f615f7f93d830e55e6fe4f04d214b93d8cb4b53
Date:   Tue Jul 10 14:10:44 2012 -0700

2012年8月13日月曜日

Android NDK で COLLADA DOM を使ってみる【基本設定編】

目的

Android NDK で COLLADA dom ライブラリをビルド - TOP」でビルドした、COLLADA DOM ライブラリを、実際に使ってみる。

最初は、基本的な設定を行う。これらの設定は、NativeActivity を利用して、C/C++ だけで、Android のアプリを作成するために行う。

はじめに

COLLADA DOM ライブラリは、ビルド済みで、同一ワークスペースに存在する前提とする。
COLLADA DOM で読み込む、モデルデータファイルは、Blender のエクスポートを利用して出力した。
出力されたモデルデータのバージョンは 1.4.1 となっている。

当方、C/C++ の知識は、「お遊びレベル」で、Android での「プログラミング経験無し」、さらには、「COLLADA DOMって何?おいしいの?」っていう状態ゆえに、内容については、参考程度と心得られたし。あしからず。

プロジェクト作成

「Android Application Project」を作成

「File」メニュー⇒「New」⇒「Other」を選択。
「Android」⇒「Android Application Project」を選択し、「Next」ボタンを押下。

「New Android Application」ダイアログ

Application Name:「ColladaSandbox」
Project Name:「ColladaSandbox」
Package Name:「foobar.colladasandbox」
Build SDK:「Android 2.3.1 (API 9)」
Minimum Required SDK:「API 9: Android 2.3 (Gingerbread)」
「Next」ボタンを押下。

「Configure Launcher Icon」ダイアログ

値を、任意に変更して(デフォルトのままでも可)、「Next」ボタンを押下。

「Create Activity」ダイアログ

「Create Activity」チェックボックスを外す。
(Java の Activity は利用せず、C の NativeActivity だけで実装するための設定。)
「Finish」ボタンを押下。

「C++ Project」へ変換


「ColladaSandbox」プロジェクトを選択し、「File」メニュー⇒「New」⇒「Other」を選択。
 「C/C++」⇒「Convert to a C/C++ Project (Adds C/C++ Nature)」を選択し、「Next」ボタンを押下。

Convert to C or C++:「C++ Project」を選択
Project options:「Specify project type」チェックボックスをチェックする。
Project type:「Makefile project」を選択
Toolchains:「-- Other Toolchain --」を選択
「Finish」ボタンを押下。

「C/C++」パースペクティブに変更

「Window」メニュー⇒「Perspective」⇒「Other」を選択。
「C/C++」を選択し、「OK」ボタンを押下。

ビルド設定

「ColladaSandbox」プロジェクトを選択し、「File」メニュー⇒「New」⇒「Folder」を選択。
Folder name:「jni」
「Finish」ボタンを押下。

「ColladaSandbox」プロジェクトを選択し、「Project」メニュー⇒「Properties」を選択

「C/C++ Build」


「Builder Settings」タブ
「Use default build command」チェックボックスのチェックを外す。
Build command:「${CYGWIN_HOME}/bin/bash ${NDKROOT}/ndk-build NDK_DEBUG=1 V=1」
Build directory:「${workspace_loc:/ColladaSandbox/jni}」
(「Workspace...」ボタンを押下、「ColladaSandbox」プロジェクトの「jni」ディレクトリを選択して、「OK」ボタンを押下。)

「Behaviour」タブ
Use parallel build:チェックする。
Use parallel jobs:4
(ビルド処理を並列化する。マルチコアマシンの場合に設定)
Build (Incremental build):チェックボックスは、チェックしたまま、デフォルトの"all"文字列を削除して、空にする。
「OK」ボタンを押下。

「C/C++ General」⇒「Paths and Symbols」

「Includes」タブ
Include の設定は、必須ではないが、補完機能などが利用できるので、設定しておく。
設定するパスは、ターゲットにする SDK のバージョンや、標準C++ライブラリなどによって異なる。

・「Assembly」
何も無し

・「GNU C」
${NDKROOT}/platforms/android-9/arch-arm/usr/include
${NDKROOT}/sources/android/native_app_glue

・「GNU C++」
${NDKROOT}/platforms/android-9/arch-arm/usr/include
${NDKROOT}/sources/cxx-stl/gnu-libstdc++/include
${NDKROOT}/sources/android/native_app_glue
/ColladaDom/jni/include
/ColladaDom/jni/include/1.4

ColladaDom のインクルード定義は、「Is a workspace path」チェックボックスをチェックした状態で追加した。「Workspace」ボタンを押下して選択すると、自動的にチェックが付く。


アプリ設定

「AndroidManifest.xml」ファイルを開く。

「Application」タブ

「ApplicationAttributes」エリア
Debuggable:「true」
Has code:「false」

「Application Nodes」エリア
・「Activity」定義を追加
「Add」ボタンを押下。
「Activity」を選択し、「OK」ボタンを押下。
「Activity」属性に以下の値を設定。
Name:「android.app.NativeActivity」

・アプリのライブラリ名定義を追加
「Activity」を選択して、「Add」ボタンを押下。
「Meta Data」を選択して、「OK」ボタンを押下。
「Meta Data」属性 Name:「android.app.lib_name」
「Meta Data」属性に以下の値を設定。
Value:「ColladaSandbox」
(ビルド後にできる、libColladaSandbox.so ファイルの lib と .so を除いた値を設定する)

・「Intent Filter」定義を追加
「Add」ボタンを押下。
「Intent Filter」を選択し、「OK」ボタンを押下。
属性の設定は、無し。

・「Action」定義を追加
「Intent Filter」を選択して、「Add」ボタンを押下。
「Action」を選択して、「OK」ボタンを押下。
「Action」属性に以下の値を設定。
Name:「android.intent.action.MAIN」

・「Category」定義を追加
「Intent Filter」を選択して、「Add」ボタンを押下。
「Category」を選択して、「OK」ボタンを押下。
「Category」属性に以下の値を設定。
Name:「android.intent.category.LAUNCHER」


「Permissions」タブ

パーミッションには、アプリで必要なものを設定する。
今回は、SDカードにファイルを書き出すための、パーミッションを設定する。
「Add」ボタンを押下。
「Uses Permission」を選択して、「OK」ボタンを押下。
「Uses Permission」属性に以下の値を設定。
Name:「android.permission.WRITE_EXTERNAL_STORAGE」

設定後の「AndroidManifest.xml」は、こんな風になった。
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="foobar.colladasandbox"
    android:versionCode="1"
    android:versionName="1.0">

    <uses-sdk android:minSdkVersion="9" android:targetSdkVersion="15" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

    <application android:label="@string/app_name"
        android:icon="@drawable/ic_launcher"
        android:theme="@style/AppTheme" android:hasCode="false" android:debuggable="true">
        <activity android:name="android.app.NativeActivity">
            <meta-data android:name="android.app.lib_name" android:value="ColladaSandbox"/>
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>

    </application>

</manifest>


Android NDK で COLLADA DOM を使ってみる【実践編】

目的

Android NDK で COLLADA dom ライブラリをビルド - TOP」でビルドした、COLLADA DOM ライブラリを、実際に使ってみる。

Android ネイティブアプリ作成の基本的なことは、習得済みという前提で、COLLADA DOM ライブラリを利用する部分だけを、ピックアップして説明する。
ただし、今回は、ファイルのロードと、セーブのみ。OpenGL ES での表示は、行わないこととする。

基本的な設定については、「Android NDK で COLLADA DOM を使ってみる【基本設定編】」に記載してある。

モデルデータ

モデルデータは、Blender で生成したものを利用する。
他にも、「COLLADA Model Bank」のサイトで、モデルデータをダウンロードするなどの手段がある。

ファイル名は、「sample.dae」とし、「assets」ディレクトリに格納することとする。

Makefile 作成

Android.mk ファイルの方は、COLLADA DOM のインクルードパスおよび、ライブラリパスが、フルパス指定になっているので、各自の環境に合わせて修正する必要がある。

【jni/Application.mk】

APP_MODULES := ColladaSandbox
APP_ABI := armeabi-v7a
APP_PLATFORM := android-9
APP_STL := gnustl_static

【jni/Android.mk】

LOCAL_PATH := $(call my-dir)

#
# ColladaSandbox
#
include $(CLEAR_VARS)
LOCAL_MODULE := ColladaSandbox
LOCAL_ARM_MODE := arm
LOCAL_CPPFLAGS := -fexceptions
# COLLADA_DOM_SUPPORT141 を定義しないと、DAE.load() 実行時に次のようなエラーとなる。
# 「libc(7688): Fatal signal 11 (SIGSEGV) at 0x656c6962 (code=1)」
LOCAL_CPPFLAGS += -DCOLLADA_DOM_SUPPORT141

LOCAL_SRC_FILES := $(wildcard *.c *.cpp)
LOCAL_C_INCLUDES := \
    E:/work/Repositories/git/ColladaDom/ColladaDom/jni/include \
    E:/work/Repositories/git/ColladaDom/ColladaDom/jni/include/1.4 \
    E:/work/Repositories/git/ColladaDom/ColladaDom/jni/external-libs/boost

LOCAL_STATIC_LIBRARIES := \
    android_native_app_glue

LOCAL_LDLIBS := \
    -LE:/work/Repositories/git/ColladaDom/ColladaDom/obj/local/armeabi-v7a \
    -lcollada_dom \
    -lcollada_STLDatabase \
    -lcollada_stdErrPlugin \
    -lpcrecpp \
    -lpcre \
    -ltinyxml \
    -lminizip \
    -lboost_filesystem \
    -lboost_system \
    -llog \
    -landroid \
    -lEGL \
    -lGLESv1_CM \
    -lz \
    -lgnustl_static

include $(BUILD_SHARED_LIBRARY)

$(call import-module,android/native_app_glue)

COLLADA DOM ログ出力

COLLADA DOM には、エラー出力機能をプラグインできる機能がある、デフォルトでは、標準出力にログが出る。
そのログを、LogCat に出力するように、プラグインを作成する。
ただ、今のところ、ログが出力されたところを、見たことが無い・・・

【jni/LogCatErrorHandler.h】

/*
 * LogCatErrorHandler.h
 */

#ifndef LOGCATERRORHANDLER_H_
#define LOGCATERRORHANDLER_H_
#include <dae/daeErrorHandler.h>
namespace AndroidUtility {

class DLLSPEC LogCatErrorHandler: public daeErrorHandler {
public:
    LogCatErrorHandler();
    virtual
    ~LogCatErrorHandler();

public:
    void
    handleError(daeString msg);
    void
    handleWarning(daeString msg);
};

} /* namespace AndroidUtility */
#endif /* LOGCATERRORHANDLER_H_ */

【jni/LogCatErrorHandler.cpp】

/*
 * LogCatErrorHandler.cpp
 */

#include <android/log.h>
#include <dae/daeTypes.h>
#include "LogCatErrorHandler.h"

#define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, "LogCatErrorHandler", __VA_ARGS__))
#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, "LogCatErrorHandler", __VA_ARGS__))

namespace AndroidUtility {

LogCatErrorHandler::LogCatErrorHandler() {
}

LogCatErrorHandler::~LogCatErrorHandler() {
}

void LogCatErrorHandler::handleError(daeString msg) {
    LOGE("%s", msg);
}

void LogCatErrorHandler::handleWarning(daeString msg) {
    LOGW("%s", msg);
}
}
/* namespace AndroidUtility */

メイン処理

メイン処理は、NDK に付属する「native_app_glue」を利用する、これは、「native_activity」をラッピングし、より手軽に実装できるようにしたもの。
実装は、NDK に付属してきたサンプルプロジェクト「native-activity」の「main.c」を変更して行った。
160行目あたりにサブ処理を呼び出す部分がある。

【jni/main.c】

/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */
/*
 * AbsoluteArea has modified this file.
 * The original license is provided above for reference and legal purposes.
 */

#include <jni.h>
#include <errno.h>

#include <EGL/egl.h>
#include <GLES/gl.h>

#include <android/log.h>
#include <android_native_app_glue.h>

#include "Sub.h"

#define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, "main", __VA_ARGS__))

struct saved_state {
    float angle;
    int32_t x;
    int32_t y;
};

struct engine {
    struct android_app* app;

    int animating;
    EGLDisplay display;
    EGLSurface surface;
    EGLContext context;
    int32_t width;
    int32_t height;
    struct saved_state state;
};

static int engine_init_display(struct engine* engine) {
    const EGLint attribs[] = { EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_BLUE_SIZE,
            8, EGL_GREEN_SIZE, 8, EGL_RED_SIZE, 8, EGL_NONE };
    EGLint w, h, dummy, format;
    EGLint numConfigs;
    EGLConfig config;
    EGLSurface surface;
    EGLContext context;

    EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
    eglInitialize(display, 0, 0);
    eglChooseConfig(display, attribs, &config, 1, &numConfigs);
    eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format);
    ANativeWindow_setBuffersGeometry(engine->app->window, 0, 0, format);

    surface = eglCreateWindowSurface(display, config, engine->app->window,
            NULL);
    context = eglCreateContext(display, config, NULL, NULL);

    if (eglMakeCurrent(display, surface, surface, context) == EGL_FALSE) {
        LOGW("Unable to eglMakeCurrent");
        return -1;
    }

    eglQuerySurface(display, surface, EGL_WIDTH, &w);
    eglQuerySurface(display, surface, EGL_HEIGHT, &h);

    engine->display = display;
    engine->context = context;
    engine->surface = surface;
    engine->width = w;
    engine->height = h;
    engine->state.angle = 0;

    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
    glEnable(GL_CULL_FACE);
    glShadeModel(GL_SMOOTH);
    glDisable(GL_DEPTH_TEST);

    return 0;
}

static void engine_draw_frame(struct engine* engine) {
    if (engine->display == NULL) {
        return;
    }
    glClearColor(((float) engine->state.x) / engine->width, engine->state.angle,
            ((float) engine->state.y) / engine->height, 1);
    glClear(GL_COLOR_BUFFER_BIT);
    eglSwapBuffers(engine->display, engine->surface);
}

static void engine_term_display(struct engine* engine) {
    if (engine->display != EGL_NO_DISPLAY) {
        eglMakeCurrent(engine->display, EGL_NO_SURFACE, EGL_NO_SURFACE,
                EGL_NO_CONTEXT);
        if (engine->context != EGL_NO_CONTEXT) {
            eglDestroyContext(engine->display, engine->context);
        }
        if (engine->surface != EGL_NO_SURFACE) {
            eglDestroySurface(engine->display, engine->surface);
        }
        eglTerminate(engine->display);
    }
    engine->animating = 0;
    engine->display = EGL_NO_DISPLAY;
    engine->context = EGL_NO_CONTEXT;
    engine->surface = EGL_NO_SURFACE;
}

static void engine_handle_cmd(struct android_app* app, int32_t cmd) {
    struct engine* engine = (struct engine*) app->userData;
    switch (cmd) {
    case APP_CMD_SAVE_STATE:
        engine->app->savedState = malloc(sizeof(struct saved_state));
        *((struct saved_state*) engine->app->savedState) = engine->state;
        engine->app->savedStateSize = sizeof(struct saved_state);
        break;
    case APP_CMD_INIT_WINDOW:
        if (engine->app->window != NULL) {
            engine_init_display(engine);
            engine_draw_frame(engine);
        }
        break;
    case APP_CMD_TERM_WINDOW:
        engine_term_display(engine);
        break;
    case APP_CMD_LOST_FOCUS:
        engine->animating = 0;
        engine_draw_frame(engine);
        break;
    }
}

void android_main(struct android_app* state) {
    struct engine engine;
    app_dummy();
    memset(&engine, 0, sizeof(engine));
    state->userData = &engine;
    state->onAppCmd = engine_handle_cmd;
    engine.app = state;

    if (state->savedState != NULL) {
        engine.state = *(struct saved_state*) state->savedState;
    }

    /* COLLADA DOM LOAD AND SAVE */
    init(state->activity->assetManager);
    loadModel();
    saveModel(state->activity->externalDataPath);
    cleanup();

    while (1) {
        int ident;
        int events;
        struct android_poll_source* source;
        while ((ident = ALooper_pollAll(engine.animating ? 0 : -1, NULL,
                &events, (void**) &source)) >= 0) {
            if (source != NULL) {
                source->process(state, source);
            }
            if (state->destroyRequested != 0) {
                engine_term_display(&engine);
                return;
            }
        }
        if (engine.animating) {
            engine_draw_frame(&engine);
        }
    }
}

サブ処理

サブ処理には、COLLADA DOM の操作部分を記述してある。

【jni/Sub.h】

/*
 * Sub.h
 */

#ifndef SUB_H_
#define SUB_H_
#include <android/asset_manager.h>
#ifdef __cplusplus
#include "LogCatErrorHandler.h"
using namespace AndroidUtility;

class Sub {
private:
    DAE *dae;
    AAssetManager *asset_manager;
public:
    Sub(AAssetManager *asset_manager);
    ~Sub();
    void loadModel();
    void saveModel(const char *externalDataPath);
};

extern "C" {
#endif /* __cplusplus */

extern void init(AAssetManager *asset_manager);
extern void loadModel();
extern void saveModel(const char *externalDataPath);
extern void cleanup();

#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* SUB_H_ */

【jni/Sub.cpp】

/*
 * Sub.cpp
 */

#include <stdio.h>
#include <dae.h>
#include <dom/domCOLLADA.h>
#include <android/log.h>
#include <android/asset_manager.h>
#include "Sub.h"
#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "Sub", __VA_ARGS__))
#define LOGW(...) ((void)__android_log_print(ANDROID_LOG_WARN, "Sub", __VA_ARGS__))
#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, "Sub", __VA_ARGS__))
using namespace AndroidUtility;

/*
 * Sub class
 */
Sub::Sub(AAssetManager *asset_manager) {
    this->asset_manager = asset_manager;
    dae = new DAE();
}

Sub::~Sub() {
    delete dae;
}

void Sub::loadModel() {
    // Asset から、モデルデータを読み込む
    AAsset *model = AAssetManager_open(asset_manager, "sample.dae", AASSET_MODE_UNKNOWN);
    size_t size = AAsset_getLength(model);
    char *buffer = new char[size + 1];
    AAsset_read(model, buffer, size);

    LOGI("Before geometry count [%d]", dae->getDatabase()->getElementCount(NULL, "geometry", NULL));

    // 第一引数の URI は、データの識別子であり、unload の引数や、load、save 時のファイル名にもなる。
    // ただし、第二引数に、読込み済みモデルデータを渡した場合、ファイルからではなく、第二引数のデータを利用する。
    int iRet = dae->load("file:///sample.dae", buffer);
    if(DAE_OK != iRet) {
        // 読込みに失敗した場合
        LOGE("Load error [%d]", iRet);
        return;
    }

    LOGI("After geometry count [%d]", dae->getDatabase()->getElementCount(NULL, "geometry", NULL));

    delete buffer;
    AAsset_close(model);
}

void Sub::saveModel(const char *externalDataPath) {
    // ICONIA TAB A700 の「externalDataPath」は、
    // "/mnt/sdcard/Android/data/foobar.colladasandbox/files"になっている。
    LOGI("externalDataPath=%s", externalDataPath);
    char *uri;
    // 保存場所は、環境に合わせて変更すること。
    sprintf(uri, "file://%s%s", externalDataPath, "/../../../../sample2.dae");
    LOGI("saveURI=%s", uri);
    int iRet = dae->saveAs(uri, "file:///sample.dae", true);
    LOGI("iRet [%d], %s", iRet, strerror(errno));
    if(DAE_OK != iRet) {
        // なぜだか、保存に失敗しても、DAE_OK が返ってくる。なんでだんべ・・・
        LOGE("Failed to save the file.");
    }
}

/*
 * 以下、main.c から呼び出される関数
 */

Sub *sub;

extern "C" {
void init(AAssetManager *asset_manager) {
    sub = new Sub(asset_manager);
    // COLLADA DOM に、エラーハンドラを設定
    // ただ、今のところ、メッセージが出力された所を、見たことが無い・・・
    LogCatErrorHandler *errHandler = new LogCatErrorHandler();
    daeErrorHandler::setErrorHandler(errHandler);
    // ログを出力してみる
    daeErrorHandler::get()->handleWarning("LogCatErrorHandler READY!!!");
}

void loadModel() {
    sub->loadModel();
}

void saveModel(const char *externalDataPath) {
    sub->saveModel(externalDataPath);
}

void cleanup() {
    // アプリケーションが、終了する前の大掃除
    DAE::cleanup();
}

}

最終的にプロジェクトツリーは、こんな風になった。

2012年8月11日土曜日

Android NDK で COLLADA dom ライブラリをビルド - tinyxml ビルド用設定


Android NDK で COLLADA dom ライブラリをビルド - pcre ビルド用設定


Android NDK で COLLADA dom ライブラリをビルド - minizip ビルド用設定


Android NDK で COLLADA dom ライブラリをビルド - boost ビルド用設定


Android NDK で COLLADA dom ライブラリをビルド - ビルド用プロジェクトを作成


Android NDK で COLLADA dom ライブラリをビルド - 必要なもの


Android NDK で COLLADA dom ライブラリをビルド - TOP


Android NDK で COLLADA dom ライブラリをビルド - ビルド実行


2012年8月4日土曜日

ICONIA TAB A700 の USB ドライバインストールで泣いた

書いておいてなんだが。この方法は、お勧めできない。真似しちゃダメ、ゼッタイ。

環境
Windows Vista Business 64ビット SP2


 ICONIA TAB A700 を、Tegra3 研究開発用に買ってきたのだが、肝心の UBS ドライバをインストールできない。
発売後、しばらく acer の日本語ページには、USB ドライバがなく、ドライバをインストールする前、耐え切れずに USB 接続をしてしまった、せいかもしれない。

しかも、ドライバのインストーラーのエラー表示では、XP およびWindows7 以外には、対応していないようにも、読み取れた。「けっ、Vista は味噌っかすかよっ!」って。
でも、インストール途中で、インストールディレクトリをのぞくと、Vista のドライバも入っているぞと。

で、強硬手段に打って出た。
エラー表示ダイアログを閉じると、インストール先のファイルが、きれいさっぱり消されてしまうので、
開いたままにして。
デバイスマネージャから、A700 デバイスのドライバを更新を実行。
ドライバを手動で選択するようにして、上記のインストール先を指定して実行。
これで、とりあえずはドライバがインストールできる。
ただし、アンインストールとかできなくなる。

自己責任でどうぞ。

2012年7月29日日曜日

Android に関する備忘録集

はじめに

ここに書いてあることは、夢です。目が覚めたら、全て忘れてしまうことでしょう。

動作環境

  • Windows Vista Business 64bit SP2
  • AMD Phenom II X4 955 3.2GHz
  • Tegra Android Developer Pack 1.0r8
    • Android SDK r18
    • Android NDK r8
    • JDK 6u24
    • Cygwin 1.7
    • Eclipse 3.7.1
    • CDT 8.0.0
    • ADT 15.0.0
    • Apache Ant 1.8.2
    • NVIDIA Debug Manager for Eclipse 12.0.0
    • Tegra Sample Code
「Tegra Android Developer Pack 1.0r8」のインストールは、”E:\appli\NVPACK”に行っている。

2012年2月26日日曜日

【悠々自炊ライフ】自炊始めました!(その3)

自炊のフィルター処理を GIMP でバッチ化できたが、複数の CPU がある場合、有効活用できていない。そんなのい・や・だ!

というわけで、バッチのマルチスレッド化に着手してみた。

基本コンセプトは、バッチ処理をキュー化し、キューを処理するバッチを並列で起動する。
バッチは、すべて windows 標準機能だけで動作するようになっている。
Java とか使えば、もっとシンプルになるのだが、バッチでやることに意味があるのだよ。フッフッフ・・・

Windows でファイルやフォルダをつかんでいるプロセスを調べる

Windows でファイルやフォルダをつかんでいるプロセスを調べる

超備忘録

Process Explorer を起動
「Find」メニューから「Find Handle or DLL...」を選択
「Handle or DLL substring」欄に、ファイル名やディレクトリ名を入力

2012年2月5日日曜日

Ant でファイル(ワイルドカード指定)の存在をチェックするタスクを書く

Ant タスクで、ワイルドカード指定してファイルの存在チェックを行いたくなった。
Ant 1.7 以降なら、以下の方法で実現可能である。(ファイルは UTF-8 で保存すること)

【build.xml】
<?xml version="1.0" encoding="UTF-8"?>
<project name="MyProject" default="main" basedir=".">

  <!-- 検索対象ディレクトリを設定 -->
  <property name="src" location="src"/>

  <!-- 最初に呼び出される。init および caution を事前に呼び出す -->
  <target name="main" depends="init, caution" />

  <!-- 指定ファイルが存在したら、"caution"プロパティをセットする -->
  <target name="init">
    <!-- 条件を満たしたら、"caution" プロパティがセットされる -->
    <condition property="caution">
      <!-- リソース数をカウントし、0件より多かったら true となる -->
      <resourcecount when="greater" count="0">
        <!-- src 以下全ディレクトリの"Abstract*.java"ファイルをカウント対象とする -->
        <fileset dir="${src}" includes="**/Abstract*.java" />
      </resourcecount>
    </condition>
  </target>

  <!-- "caution"プロパティが設定されている場合、実行される -->
  <target name="caution" if="caution">
    <fileset id="files" dir="${src}" includes="**/Abstract*.java" />
    <pathconvert pathsep="${line.separator}" property="filelist" refid="files" />
    <fail message="以下の Abstract ファイルが含まれています${line.separator}${filelist}" />
  </target>

</project>

2012年1月3日火曜日

dnsmasq の設定

ローカルネットワーク内のホスト名を引くための、DNSプロキシとして dnsmasq を設定する。

dnsmasq をインストール
$ sudo aptitude install dnsmasq

設定ファイルを修正
$ sudo vi /etc/dnsmasq.conf

local=/localnet/
no-dhcp-interface=eth0
cache-size=500

保存して終了

このマシンの DNS 設定に dnsmasq を加える
$ sudo vi /etc/dhcp3/dhclient.conf

prepend domain-name-servers 127.0.0.1

保存して終了
上記設定を行うと、/etc/resolv.conf が自動生成されるときに、nameserver 127.0.0.1 が追加される。

hosts にローカルネットワークのマシンを定義
$ sudo vi /etc/hosts

127.0.0.1 localhost pc1
192.168.1.101 pc1
192.168.1.102 pc2

保存して終了

dnsmasq を起動
$ sudo /etc/init.d/dnsmasq restart

ネットワーク(eth0)を再起動
$ sudo ifconfig eth0 down
$ sudo ifconfig eth0 up

他の PC から ping ができたら完了。

Ubuntu で RAID10 の故障ハードディスクを取替え

RAID 復旧作業の備忘録

以前、RAID 復旧作業で、HDD のパーティションを切ることができず、ドライブ丸ごと RAID に突っ込んだ苦い失敗を、ここで挽回する。

今回、2度目の HDD 故障となり、HDD を Amazon でポチることにした。しかし容量が 2T のものしかなかったので、現在の 1.5T 構成だと、500GB 無駄になることになる。
さすがに、500GB 無駄になるのは、甚だ遺憾なので、真面目に対処することにした。

前回の失敗を振り返ると、、「GUI での設定方法がよく分かっていなかった」ことに尽きる。

そこらへんを重点的に攻略していこうと思ったが、やはり GUI では、思ったように設定できないようだ。