2012年4月アーカイブ

バージョン情報を付加する

| コメント(0) | トラックバック(0)   このエントリーをはてなブックマークに追加 このエントリーを含むはてなブックマーク

本題からは離れるが、実行ファイルにバージョン情報を付加することを考える。
本来なら、ソフトが出来上がった後にやればいいことだ。
なぜこの段階でこんなことする気になったのだろうか。謎だ。

さて、ここでのバージョン情報とは、
エクスプローラー上で実行ファイルを右クリックして表示されるポップアップメニューから
「プロパティ」を選択して、「詳細」タブに表示される各種情報のことだ。
ファイルの説明とかバージョンとか、著作権を表示することができる。
Visual StudioやBCBであれば、プロジェクトのプロパティで
それぞれの項目を指定してビルドすると、自動的にバージョン情報が実行ファイルに付加されるのだが
これを自力で行う場合、リソースファイルというものを使用する。

こんなファイルを用意する。(version.rc)

#include <winver.h>
 
//
// Version Information
//
 
VS_VERSION_INFO    VERSIONINFO
FILEVERSION     1,0,0,0
FILEFLAGSMASK   VS_FFI_FILEFLAGSMASK
FILEFLAGS       VS_FF_PRERELEASE
FILEOS          VOS_NT_WINDOWS32
FILETYPE        VFT_APP
{
    BLOCK "StringFileInfo"
    {
        BLOCK "041104b0"
        {
            VALUE "CompanyName",      "ColorWorks\0"
            VALUE "FileDescription",  "SampleWindow\0"
            VALUE "FileVersion",      "<FILEVERSION>\0"
            VALUE "InternalName",     "Sample\0"
            VALUE "OriginalFileName", "Sample.exe\0"
            VALUE "LegalCopyright",   "(C)ColorWorks\0"
            VALUE "ProductName",      "Sample\0"
            VALUE "ProductVersion",   "3.10\0"
        }
    }
    BLOCK "VarFileInfo"
    {
        VALUE "Translation", 0x411, 1200
    }
}

それぞれの項目の詳細は...誰か教えてくださいorz
これに関わるネット上の情報が古いことから、
最近ではバージョン情報を実行ファイルに付与すること自体がナンセンスなのかもしれない。

いくつか、ポイントを書いておく。

1行目のwinver.hは、代わりにwindows.hでも可。
なぜならwindows.hの中でwinver.hをインクルードしているため。

ファイルのバージョンは、8行目のFILEVERSIONの後に記載する。
数字はカンマ区切りであり、ピリオドでは区切らない。

16行目の"041104b0"は、日本語のコードページを表す。
英語のコードページだと"040904b0"になるらしい。

30行目の0x411, 1200は、16行目の"041104b0"に合わせる。
上4桁の0411はそのまま16進数で0x0411、下4桁の04b0は10進数に変換して1200。
合わせなくてもコンパイルできるが、合わせないとバージョン情報が適切に表示されない。

18行目のCompanyNameは会社名。サークル名でも良いと思う。
19行目のFileDescriptionはファイルの説明。
20行目のFileVersionはファイルのバージョン。<FILEVERSION>とすると、先に指定した値が参照される。
21行目のInternalNameは内部名。ハッキリ言って要らない気がする。
22行目のOriginalFileNameは元のファイル名。同上。
23行目のLegalCopyrightは著作権。
24行目のProductNameは製品名。
25行目のProductVersionは製品バージョン。ファイルバージョンとは異なる。

さて、ファイルが出来上がったら、ビルドすればOKなのだが、
これがEclipse+MinGW環境ではかなり厄介であった。

ちなみに、コマンドラインからMinGWでビルドするなら、次のようにすればよい。
1.windresでversion.rcをコンパイルし、version.oを出力
> windres ..\src\version.rc src\version.o
2.SampleWindow.cppをコンパイルし、SampleWindow.oを出力
> g++ -Wall -c -o src\SampleWindow.o ..\src\SampleWindow.cpp
3.SampleWindow.oとversion.oをリンクし、実行ファイルを作成
> g++ -mwindows -o Sample.exe src\SampleWindow.o src\version.o -lgdi32

これを踏まえて、Eclipseでは次のように行う。
1.プロジェクトのプロパティから左側のツリービューで「C/C++ビルド」→「設定」を選択
2.設定ウィンドウの中で「ビルド・ステップ」タブを選択し、ビルド前のステップのコマンド欄に
  windres ../src/version.rc -o version.o と入力する。
3.設定ウィンドウを閉じて、一度ビルドする。(「プロジェクト」→「すべてビルド」)
4.プロジェクトエクスプローラーを選択してリフレッシュする(F5キーでも可)
  すると、プロジェクトエクスプローラー上にversion.oが表示される。
5.再度プロジェクトのプロパティを開き、
  設定ウィンドウの「ツール設定」タブを選択し、「MinGW C++ Linker」→「その他」を選択
  「その他のオブジェクト」の右にある追加アイコンを選択すると、ファイルの入力ダイアログが表示される。
  「ワークスペース」ボタンを押し、上で出力されたversion.oを選択してダイアログを閉じる。
6.もう一度ビルドする。

ああ面倒くさい。

さらに面倒なことに、Eclipseは一度ビルドしたプログラムを再度ビルドしようとしても
ソースコードが変わっていなければ「再ビルドの必要なし」と判断してしまうのだが
リソースファイルはソースコードでないと思われているのか、
リソースファイルだけを変更して再ビルドしようとしても反映されない。
また、一度「プロジェクト」→「クリーン」で生成されたオブジェクトファイル等をクリアしてしまうと
再ビルドそのものがエラーになってしまう。

**** Internal Builder is used for build ****
Build error
Path must include project and resource name: /Sample

こうなってしまった場合は、
上記5で設定したversion.oのリンク設定を一旦削除し、
3以降の手順を行えば生成される。

ああ面倒くさい。
makefileで片づける方がよっぽど楽な気がする。