Archive for 2008/12

sourcesファイルにおけるサブディレクトリ指定

「なんだ、それ?dir ファイルにサブディレクトリを書くだけでしょ。」というのが、たぶん普通の反応なんだと思います。たしかに、Windows Embedded CE の流儀では、それが正しいやり方です。

以下で説明するのは、WinCE の流儀には忠実でないやり方で、PlatformBuilder の OSDesign サブプロジェクトを作る方法です。この方法は、クロスプラットフォームのオープンソースのライブラリを WinCE で利用したり、あるいは、将来的なクロスプラットフォームでの利用も想定して、可搬性の高いコードやプロジェクトを作る場合に、役立つのではないかと思います。

さて、「方法」と書きましたが、実際は、そんなに大袈裟なものでは、ありません。単に、sources ファイルにターゲット(オブジェクトファイル)の生成規則を追加するだけです。生成規則は、
 <WINCE600_Root>/PUBLIC/COMMON/OAK/MISC/
にある makefile.def ファイルに記述されています。たとえば、makefile を配置したディレクトリの、一つ上のディレクトリに存在する .cpp ファイルに対するオブジェクトファイルの生成規則は、次の通りです:

{..\}.cpp{$(_OBJDIR)\}.obj:
    @echo BUILD_MARKER:CPP_COMPILE_START Compiling $<
    @type <<
$(ECHO_CXX_MSG)
<<NOKEEP
    @$(CXXCOMPILER) @<< $(CONLY_FLAGS) -Fo$@
$(C_COMMAND_LINE_OPTIONS: =
) $(MAKEDIR)\$<
<<NOKEEP
    @echo BUILD_MARKER:CPP_COMPILE_END

この生成規則があるため、次のようなディレクトリ構成で PlatformBuilder サブプロジェクトを作成しても、正しくビルドされるのです。

 MySubProj/
  myprojsrc.cpp
  myprojsrc2.cpp
  WCEPB/
   makefile
   MySubProj.pbpxml
   postlink.bat
   prelink.bat
   ProjSysgen.bat
   sources

上の例では、MySubProj/ というディレクトリが、PlatformBuilder サブプロジェクトのソースディレクトリです。この中の、WCEPB/ というサブディレクトリに PlatformBuilder のプロジェクトファイルを配置しています。この例では、sources ファイルでは、SOURCES マクロが次のように定義されているはずです:

 SOURCES= \
   ..\myprojsrc.cpp \
   ..\myprojsrc2.cpp \

ここで、上の例とは異なり、ソースファイル用のサブディレクトリがある場合には、makefile.def ファイルに記述された生成規則だけではビルドできません。次のようなディレクトリ構成の場合です。

 MySubProj2/
  myprojsrc.cpp
  myprojsrc2.cpp
  SubDir/
   subdirsrc.cpp
  WCEPB/
   …(※上の例と同じ)

この場合、sources ファイルで SOURCES マクロを次のように書いても、ビルドエラーとなります。

 SOURCES= \
   ..\myprojsrc.cpp \
   ..\myprojsrc2.cpp \
   ..\SubDir\subdirsrc.cpp \

ビルドエラーのメッセージは、次のようになる筈です。

 NMAKE :  U1073: don’t know how to make ‘obj\ARMV4I\debug\subdirsrc.obj’

これは、subdirsrc.cpp に対応するオブジェクトファイルの生成規則が見つからないからです。従って、sources ファイルに次の生成規則を追加することにより、このエラーを解消できます:

# for source files in ‘SubDir/’ dir
{..\SubDir\}.cpp{$(_OBJDIR)\}.obj:
    @echo BUILD_MARKER:CPP_COMPILE_START Compiling $<
    @type <<
$(ECHO_CXX_MSG)
<<NOKEEP
    @$(CXXCOMPILER) @<< $(CONLY_FLAGS) -Fo$@
$(C_COMMAND_LINE_OPTIONS: =
) $(MAKEDIR)\$<
<<NOKEEP
    @echo BUILD_MARKER:CPP_COMPILE_END

サブディレクトリに配置するソースファイルが、C++ のソース(.cpp)ではなく C のソース(.c)の場合に、どのような生成規則を追加すればよいのかは、makefile.def を御覧になってみて下さい。’BUILD_MARKER:C_COMPILE_START’ という文字列で検索すれば、すぐに見つかるでしょう :-)

1 comment 2008/12/14 koga

C++標準ライブラリの使用

■PlatformBuilder サブプロジェクト
そんなことを考える人というのは、どちらかといえば少数派だと思うのですが、Windows Embedded CE の PlatformBuilder サブプロジェクトで C++ 標準ライブラリを使いたい、という場合があります。

std::vector や std::list など、STL の基本的なコンテナを使いたい、という場合は、それでも特に問題ありません。WinCE 6.0 の開発環境では、それらがサポートされています。どの程度のサポートがあるか興味がある方は、
 <WINCE600_Root>/PUBLIC/COMMON/SDK/INC/
に入っているヘッダファイルを見てみて下さい。

C++ の標準ライブラリを普段から多用している方であれば、上記のヘッダファイル一覧を眺めた時に、C++ 用のヘッダファイルが若干少ないように思われるんじゃないかと思います。ただし、「いや、若干どころか、全然少ないよ」と思われたのであれば、エクスプローラの「詳細」表示でソートキーを「種類」にして、C++ 用のヘッダファイル(拡張子がないやつです)が固まって並ぶようにして下さい。<WINCE600>/PUBLIC/COMMON/SDK/INC/ には、C/C++ の標準ライブラリ用のヘッダだけでなく、Win32 API の基本的なヘッダファイルも収録されていますので、それらの間に混じると、実際よりも少なく感じてしまうかも知れません。

さて、C++ 用のヘッダファイルが若干少ないように思える理由の一つは、iostream 系のものが無いからなのです。実は、WinCE 6.0 の PlatformBuilder が提供するライブラリには、iostream が含まれていません。これについては、MSDN のフォーラムでも、過去に話題にのぼっています:
 https://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1109574&SiteID=1

上の記事スレッドでは、PlatformBuilder の OSDesign プロジェクトのサブプロジェクトとして作成したアプリケーションのプロジェクトで、 <iostream> が見つからない、という質問が発端になっています。けっきょく、OSDesign から生成した SDK にも <iostream> は含まれないので、VS 2005 のスマートデバイスサポートに付属する、Windows Embedded CE 用の C++ 標準ライブラリを使うべし、という解答で締めくくられています。

「なんだ。じゃあ、PlatformBuilder プロジェクトではなく、VS 2005 のスマートデバイスプロジェクトにしてビルドすればいいってことか。」と思われた方は、少なくないでしょう。そう。それが、多数派だと思います。「PlatformBuilder サブプロジェクトで iostream は使えないのか?」と思ったあなた。あなたは、少数派なのでしょう。実をいうと、僕もそうなんですけどね。

■VS 2005 スマートデバイスプロジェクトだけなのか
さて、iostream を使うコードは、PlatformBuilder のサブプロジェクト(より正確には、OSDesign のサブプロジェクト)にしてもビルドできず、VS 2005 のスマートデバイスプロジェクトにしなければいけないというのでは、不便に感じることもあります。それは、そのコードをビルドしてできるアプリケーションや DLL を OS イメージ(nk.bin)に格納するのが面倒であったり、あるいは、カーネルデバッガを使ってデバッグする作業が面倒になるからです。

もちろん、C++ の iostream を使うようなアプリケーションは、OS イメージのビルドとは開発作業を完全に分離し、OSDesign から作った SDK と組み合わせることにより、VS 2005 のスマートデバイスプロジェクトとしてビルド&デバッグするのが正当なやり方だ、という意見もあるでしょう。どちらかといえば、その方が正しいのかなと思います。

しかし、一般的な Win32 API しか使わないようなアプリケーションや DLL ではなく、デバイス固有のハードウェアを制御する、デバイスドライバに依存したようなアプリケーションや DLL の場合には、実機上(あるいは、そのデバイスドライバの fake 実装を載せたエミュレータ上)で、カーネルデバッガを使ったデバッグを行いたい、という状況に至ることは少なくないと思います。そのような場合には、PlatformBuilder のプロジェクトにしておけると、取り回しが便利だと思うのです。

ただし、そもそも組込み機器向けのソフトウェアにおいて、C++ の高機能な標準ライブラリをふんだんに使うのは好ましくない、という考え方もあると思います。僕自身は、どちらかといえば、それに近い立場です。とはいえ、デスクトップ向けの Linux などで当初開発された成果物があり、それを、大きな改変なしで WinCE でも再利用したい、というような局面もあります。そういった場合において、VS 2005 のスマートデバイスプロジェクトではなく、PlatformBuilder のサブプロジェクトにしてビルド&デバッグしたいという要求があれば、以下で説明することが参考になるかも知れません。

■VS 2005 付属の C++ 標準ライブラリを PlatformBuilder で利用する
ようやく本題です。iostream や、それから、complex や hash_map など、C++ 標準ライブラリの中で、PlatformBuilder が提供していないものを、PlatformBuilder のサブプロジェクトで利用する場合には、次のような手順になるでしょう。

1.) <VS2005_Root>/VC/ ディレクトリ配下にある ce/ ディレクトリを、適当な場所へコピーする。この時、コピー先ディレクトリは、パスに空白を含んでいないものにして下さい。 
  これは、PlatfomrBuilder のビルドツールが、空白を含むパスを正しく解釈できない(と思われる)ためです。通常、VS 2005 のインストールディレクトリは、
  C:/Program Files/Microsoft Visual Studio 8/
のように、名前に空白を含みます。このため、そのパスを sources ファイルに記述してもエラーとなってしまうため、空白を含まないパスのディレクトリへコピーして使う、というわけです。
  なお、ce/ 配下を全てコピーすると、サイズが大きいので、ハードディスクの節約のために、ce/atlmfc/ ディレクトリはコピーしない方が良いかも知れません。ce/ 配下全てだと、637MB あり、そのうち、atlmfc/ が 405MB を占めています。

2.) iostream などを使っている PlatformBuilder のサブプロジェクトで、sources ファイルに記述するインクルードパスに、(1)でコピーした ce/ ディレクトリ配下の、include/ ディレクトリを追加します。

  例)
  VC8_ROOT_PATH=D:wce6utils\fromVC8

  INCLUDES= \
    $(VC8_ROOT_PATH)/ce/include \
    ;.. \
    ;../.. \

3.) (2)と同様に、sources ファイルに記述するターゲットライブラリに、(1) でコピーした ce/ ディレクトリ配下にある、C++ 標準ライブラリの static library(libcpmt.lib)を追加します。

  例)
  TARGETLIBS= \
    $(_SYSGENSDKROOT)\lib\$(_CPUINDPATH)\wininet.lib \
    $(VC8_ROOT_PATH)\ce\lib\$(TGTCPUISANAME)\libcpmt.lib \

  なお、この例では、インクルードパス(INCLUDES)設定用に定義したマクロである VC8_ROOT_PATH を参照しています。

上記の手順を行ったら、PlatformBuilder のサブプロジェクトをビルドしてみて下さい。コンパイルエラーやリンクエラーもなく、無事にビルドできる筈です。

■最後に
VS 2005 付属の C++ 標準ライブラリについての詳細は、
 http://msdn.microsoft.com/en-us/library/ms838270.aspx
にある “Standard C++ Library 8.0″ と “Table 4. Facilities for devices in SCL 8.0″ が参考になるでしょう。

Add comment 2008/12/11 koga


Categories

Links

Posts by Authors

Recent Posts

Calendar

2008年12月
« 11月   7月 »
 123456
78910111213
14151617181920
21222324252627
28293031  

Posts by Month

Posts by Category

Meta